<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Jacopo Marrone @tresorama</title>
    <description>The latest articles on DEV Community by Jacopo Marrone @tresorama (@tresorama).</description>
    <link>https://dev.to/tresorama</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%2F757739%2F15c5c12e-27b4-44d7-a953-f7644eaf04a2.jpg</url>
      <title>DEV Community: Jacopo Marrone @tresorama</title>
      <link>https://dev.to/tresorama</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/tresorama"/>
    <language>en</language>
    <item>
      <title>Dynamic HTML Tag in React Components with the "as" prop</title>
      <dc:creator>Jacopo Marrone @tresorama</dc:creator>
      <pubDate>Thu, 21 Nov 2024 15:59:06 +0000</pubDate>
      <link>https://dev.to/tresorama/dynamic-html-tag-in-react-components-with-the-as-prop-56b8</link>
      <guid>https://dev.to/tresorama/dynamic-html-tag-in-react-components-with-the-as-prop-56b8</guid>
      <description>&lt;p&gt;Imagine you're building a reusable &lt;code&gt;&amp;lt;Section&amp;gt;&lt;/code&gt; component with React. The Section component renders an HTML &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt; tag because you hardcoded it.   However, in some cases, you might want to use an other tag instead, for example a &lt;code&gt;&amp;lt;section&amp;gt;&lt;/code&gt; HTML tag.&lt;/p&gt;

&lt;p&gt;This is a typical scenario when you want your HTML to be more semantic and SEO friendly.&lt;/p&gt;

&lt;p&gt;The solution is to let the consumer decide which HTML tag should be used to render the component.  &lt;/p&gt;

&lt;h2&gt;
  
  
  The "as" prop
&lt;/h2&gt;

&lt;p&gt;This is nothing new.&lt;br&gt;&lt;br&gt;
It's an industry standard "approach" that allows you to dynamically decide which HTML tag should be used to render the component. A lot of React Components library use it, like Chakra UI and Material UI.&lt;/p&gt;

&lt;p&gt;Without the "as" prop, you'd need to create separate components for each use case, and it makes no sense. Don't do it!&lt;/p&gt;

&lt;p&gt;This is how you consume the "as" prop&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&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;Section&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;./section&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;App&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="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Section&lt;/span&gt; &lt;span class="na"&gt;as&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"section"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;CTA&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Section&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Section&lt;/span&gt; &lt;span class="na"&gt;as&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"article"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;My Article&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Section&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Section&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;This use the default HTML tag of the component&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Section&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And this is the component definition&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;SectionProps&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;as&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ElementType&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;children&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ReactNode&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Section&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;SectionProps&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;as&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Tag&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;div&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;children&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Tag&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Tag&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt;

&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Typescript Support for the "as" prop
&lt;/h2&gt;

&lt;p&gt;React helps us with Typescript types.&lt;br&gt;&lt;br&gt;
Using the typescript's &lt;code&gt;React.ElementType&lt;/code&gt; type, provided by React, you will obtain autocomplete for your IDE, like this&lt;/p&gt;

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

&lt;p&gt;As an alternative to &lt;code&gt;React.ElementType&lt;/code&gt; you can use&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;SectionProps&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;as&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;keyof&lt;/span&gt; &lt;span class="nx"&gt;JSX&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;IntrinsicElements&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;children&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ReactNode&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;or&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;SectionProps&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;as&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;keyof&lt;/span&gt; &lt;span class="nx"&gt;HTMLElementTagNameMap&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;children&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ReactNode&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;



</description>
      <category>beginners</category>
      <category>react</category>
      <category>javascript</category>
      <category>typescript</category>
    </item>
    <item>
      <title>How to remove duplicates in Postgres SQL</title>
      <dc:creator>Jacopo Marrone @tresorama</dc:creator>
      <pubDate>Tue, 19 Nov 2024 16:46:37 +0000</pubDate>
      <link>https://dev.to/tresorama/how-to-remove-duplicates-in-postgres-sql-59ad</link>
      <guid>https://dev.to/tresorama/how-to-remove-duplicates-in-postgres-sql-59ad</guid>
      <description>

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Crossposted on my blog&lt;/strong&gt;&lt;br&gt;
You can read it &lt;a href="https://jacopomarrone.com/blog/how-to-remove-duplicates-in-postgres-sql" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Our schema
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;create&lt;/span&gt; &lt;span class="k"&gt;table&lt;/span&gt; &lt;span class="nv"&gt;"post"&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="nb"&gt;SERIAL&lt;/span&gt; &lt;span class="k"&gt;PRIMARY&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;title&lt;/span&gt; &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;255&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;content&lt;/span&gt; &lt;span class="nb"&gt;TEXT&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;create&lt;/span&gt; &lt;span class="k"&gt;table&lt;/span&gt; &lt;span class="nv"&gt;"user"&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="nb"&gt;SERIAL&lt;/span&gt; &lt;span class="k"&gt;PRIMARY&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;255&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;create&lt;/span&gt; &lt;span class="k"&gt;table&lt;/span&gt; &lt;span class="nv"&gt;"post_like"&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="nb"&gt;SERIAL&lt;/span&gt; &lt;span class="k"&gt;PRIMARY&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;post_id&lt;/span&gt; &lt;span class="nb"&gt;INTEGER&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt; &lt;span class="k"&gt;REFERENCES&lt;/span&gt; &lt;span class="n"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="n"&gt;user_id&lt;/span&gt; &lt;span class="nb"&gt;INTEGER&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt; &lt;span class="k"&gt;REFERENCES&lt;/span&gt; &lt;span class="k"&gt;user&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Now we want to ensure that each user cannot like the same post more than once.&lt;br&gt;
This can be prevented by:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;using a &lt;code&gt;unique&lt;/code&gt; constraint on the pair &lt;code&gt;post_id&lt;/code&gt; + &lt;code&gt;user_id&lt;/code&gt; columns of the &lt;code&gt;post_like&lt;/code&gt; table.&lt;/li&gt;
&lt;li&gt;or removing the &lt;code&gt;id&lt;/code&gt; column of the &lt;code&gt;post_like&lt;/code&gt; table and use a composite primary key on &lt;code&gt;post_id&lt;/code&gt; + &lt;code&gt;user_id&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But, assuming we are at a point where duplicates are already there, we need to remove them.&lt;/p&gt;
&lt;h2&gt;
  
  
  Check if there are duplicates
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;select&lt;/span&gt; 
  &lt;span class="n"&gt;post_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
  &lt;span class="n"&gt;user_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="k"&gt;count&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="n"&gt;post_like&lt;/span&gt;
&lt;span class="k"&gt;group&lt;/span&gt; &lt;span class="k"&gt;by&lt;/span&gt; &lt;span class="n"&gt;post_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;user_id&lt;/span&gt;
&lt;span class="k"&gt;having&lt;/span&gt; &lt;span class="k"&gt;count&lt;/span&gt;&lt;span class="p"&gt;(&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="mi"&gt;2&lt;/span&gt;
&lt;span class="p"&gt;;&lt;/span&gt;

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

&lt;/div&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;| post_id | user_id | count |
| ------- | ------- | ----- |
| 3       | 2       | 2     |
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This output tells us that user &lt;code&gt;2&lt;/code&gt; has liked post &lt;code&gt;3&lt;/code&gt; more than one time, specifically 2 times.&lt;/p&gt;
&lt;h2&gt;
  
  
  Remove duplicates
&lt;/h2&gt;

&lt;p&gt;Now that we know that there are duplicates, we can remove them.&lt;br&gt;&lt;br&gt;
We split this process in two step:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;read duplicates&lt;/li&gt;
&lt;li&gt;remove duplicates (dry run)&lt;/li&gt;
&lt;li&gt;remove duplicates (real run)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Read duplicates&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Transaction rollback&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
To test our queries without removing real data, until we are sure the query is correct, we use the transaction &lt;code&gt;rollback&lt;/code&gt; feature.&lt;br&gt;&lt;br&gt;
By doing this our query will never be committed, is similar to the&lt;br&gt;
"dry run" concept that you can find on other applications (like&lt;br&gt;
rsync).&lt;/p&gt;
&lt;/blockquote&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;CTE&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
We use &lt;code&gt;CTE&lt;/code&gt; because it provides a good DX.&lt;br&gt;&lt;br&gt;
With &lt;code&gt;CTE&lt;/code&gt;, we can run a query, store the results in a temporary table, and then use the same table for subsequent queries.&lt;br&gt;&lt;br&gt;
This mental model is similar to what we usually do in coding by creating a temporary variable.  &lt;/p&gt;

&lt;p&gt;The CTE syntax is &lt;/p&gt;


&lt;pre class="highlight sql"&gt;&lt;code&gt; &lt;span class="k"&gt;with&lt;/span&gt; 
 &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;cte_name&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
   &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
 &lt;span class="p"&gt;),&lt;/span&gt;
 &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;cte_name_2&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
   &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;query_2&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="c1"&gt;-- here we can refernce &amp;lt;cte_name&amp;gt;&lt;/span&gt;
 &lt;span class="p"&gt;)&lt;/span&gt;
 &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;final_query&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="c1"&gt;-- here we can refernce &amp;lt;cte_name&amp;gt; and &amp;lt;cte_name_2&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/blockquote&gt;

&lt;p&gt;With both transaction and CTE, we can do the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;begin&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;-- start transaction&lt;/span&gt;

&lt;span class="k"&gt;with&lt;/span&gt;
&lt;span class="n"&gt;duplicates_info&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="k"&gt;select&lt;/span&gt;
    &lt;span class="n"&gt;row_number&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="n"&gt;over&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="k"&gt;partition&lt;/span&gt; &lt;span class="k"&gt;by&lt;/span&gt; &lt;span class="n"&gt;post_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;user_id&lt;/span&gt; &lt;span class="k"&gt;order&lt;/span&gt; &lt;span class="k"&gt;by&lt;/span&gt; &lt;span class="n"&gt;user_id&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;group_index&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;post_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;user_id&lt;/span&gt;
  &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="n"&gt;post_like&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;select&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;
&lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="n"&gt;duplicates_info&lt;/span&gt;
&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;rollback&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;-- ends transaction discarding every changes to the database &lt;/span&gt;

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

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;| group_index | id | post_id | user_id |
| ----------- | -- | ------- | ------- |
| 1           | 1  | 1       | 1       |
| 1           | 2  | 2       | 2       |
| 1           | 3  | 3       | 2       |
| 2           | 4  | 3       | 2       |
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The latest row of results, where &lt;code&gt;group_index&lt;/code&gt; is 2, means that this row is the second one in the group with post_id = 3 and user_id = 2.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;What happens here with the syntax?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;row_number() over (partition by ...) as group_index&lt;/code&gt; is a window function that, first group rows by the columns in the &lt;code&gt;partition by&lt;/code&gt; clause, and then assigns a number to each row, based on the index of the row in the group.  &lt;/p&gt;

&lt;p&gt;&lt;code&gt;partition&lt;/code&gt; is similar to &lt;code&gt;group by&lt;/code&gt;, because it groups the rows by a common column, but if &lt;code&gt;group by&lt;/code&gt; return only 1 row for each group, &lt;code&gt;partition&lt;/code&gt; let us add new columns to the source table based on groups.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;group_index&lt;/code&gt; is a column name alias, regular sql syntax.  &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Filter only duplicates&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Now let's keep only items with &lt;code&gt;group_index &amp;gt; 1&lt;/code&gt;, which means that the row is not the first one in the group, or in other words, it is a duplicate.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;&lt;span class="p"&gt;begin; -- start transaction
&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="p"&gt;with
duplicates_info as (
&lt;/span&gt;  select
    row_number() over (
      partition by post_id, user_id order by user_id
    ) as group_index,
    id,
    post_id,
    user_id
  from post_like
)
&lt;span class="p"&gt;select *
from duplicates_info
&lt;/span&gt;&lt;span class="gi"&gt;+ where group_index &amp;gt; 1
&lt;/span&gt;;
&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="p"&gt;rollback; -- ends transaction discarding every changes to the database 
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;| group_index | id | post_id | user_id |
| ----------- | -- | ------- | ------- |
| 2           | 4  | 3       | 2       |
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We need to remove only this row, with id &lt;code&gt;4&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Remove duplicates - dry run&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Now rewite the final query so that we read from &lt;code&gt;post_like&lt;/code&gt; table and not anymore from the cte &lt;code&gt;duplicates_info&lt;/code&gt;.&lt;br&gt;
We still use the cte &lt;code&gt;duplicates_info&lt;/code&gt; to get the &lt;code&gt;id&lt;/code&gt; of the duplicates.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;&lt;span class="p"&gt;begin; -- start transaction
&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="p"&gt;with
duplicates_info as (
&lt;/span&gt;  select
    row_number() over (
      partition by post_id, user_id order by user_id
    ) as group_index,
    id,
    post_id,
    user_id
  from post_like
)
&lt;span class="gd"&gt;- select *
- from duplicates_info
- where group_index &amp;gt; 1
&lt;/span&gt;&lt;span class="gi"&gt;+ select *
+ from post_like
+ where id in (
+  select id from duplicates_info
+  where group_index &amp;gt; 1
+ )
&lt;/span&gt;;
&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="p"&gt;rollback; -- ends transaction discarding every changes to the database 
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We will see the records that we want to remove.&lt;br&gt;&lt;br&gt;
After we checked that they are correct, we swap &lt;code&gt;select&lt;/code&gt; with &lt;code&gt;delete&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;&lt;span class="p"&gt;begin; -- start transaction
&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="p"&gt;with
duplicates_info as (
&lt;/span&gt;  select
    row_number() over (
      partition by post_id, user_id order by user_id
    ) as group_index,
    id,
    post_id,
    user_id
  from post_like
)
&lt;span class="gd"&gt;- select *
&lt;/span&gt;&lt;span class="gi"&gt;+ delete
&lt;/span&gt;&lt;span class="p"&gt;from post_like
where id in (
&lt;/span&gt; select id from duplicates_info
 where group_index &amp;gt; 1
)
&lt;span class="gi"&gt;+ returning * -- will output deleted rows
&lt;/span&gt;;
&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="p"&gt;rollback; -- ends transaction discarding every changes to the database 
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This last query is what we finally want to execute.&lt;br&gt;&lt;br&gt;
But becuase we still have &lt;code&gt;rollback&lt;/code&gt; statement, these chhanges are simulated, and not applied to the database.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Remove duplicates - real run&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Finally we can remove the duplicates for real.&lt;br&gt;
Here we use &lt;code&gt;commit&lt;/code&gt; instead of &lt;code&gt;rollback&lt;/code&gt;, so that the changes are applied to the database.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;&lt;span class="p"&gt;begin; -- start transaction
&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="p"&gt;with
duplicates_info as (
&lt;/span&gt;  select
    row_number() over (
      partition by post_id, user_id order by user_id
    ) as group_index,
    id,
    post_id,
    user_id
  from post_like
)
&lt;span class="p"&gt;delete
from post_like
where id in (
&lt;/span&gt; select id from duplicates_info
 where group_index &amp;gt; 1
)
&lt;span class="p"&gt;returning * -- output deleted rows
&lt;/span&gt;;
&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="gd"&gt;- -- ends transaction discarding every changes to the database 
- rollback; 
&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="gi"&gt;+ -- ends transaction applying changes to the database
+ commit; 
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Final Code
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- start transaction&lt;/span&gt;
&lt;span class="k"&gt;begin&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 

&lt;span class="k"&gt;with&lt;/span&gt;
&lt;span class="n"&gt;duplicates_info&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="k"&gt;select&lt;/span&gt;
    &lt;span class="n"&gt;row_number&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="n"&gt;over&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="k"&gt;partition&lt;/span&gt; &lt;span class="k"&gt;by&lt;/span&gt; &lt;span class="n"&gt;post_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;user_id&lt;/span&gt; &lt;span class="k"&gt;order&lt;/span&gt; &lt;span class="k"&gt;by&lt;/span&gt; &lt;span class="n"&gt;user_id&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;group_index&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;post_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;user_id&lt;/span&gt;
  &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="n"&gt;post_like&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;delete&lt;/span&gt;
&lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="n"&gt;post_like&lt;/span&gt;
&lt;span class="k"&gt;where&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
 &lt;span class="k"&gt;select&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="n"&gt;duplicates_info&lt;/span&gt;
 &lt;span class="k"&gt;where&lt;/span&gt; &lt;span class="n"&gt;group_index&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;returning&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="c1"&gt;-- output deleted rows&lt;/span&gt;
&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;-- ends transaction discarding every changes to the database &lt;/span&gt;
&lt;span class="c1"&gt;-- rollback; &lt;/span&gt;

&lt;span class="c1"&gt;-- ends transaction applying changes to the database&lt;/span&gt;
&lt;span class="k"&gt;commit&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;I write articles mainly to help future myself or to help the growth of tools I use in my work.&lt;/p&gt;

&lt;p&gt;If this article was helpful to you leave a like.&lt;/p&gt;

&lt;p&gt;Would you like me to talk about a particular topic?&lt;br&gt;&lt;br&gt;
Tell me in the comments !&lt;/p&gt;

</description>
      <category>sql</category>
      <category>webdev</category>
      <category>javascript</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Essential CLI commands</title>
      <dc:creator>Jacopo Marrone @tresorama</dc:creator>
      <pubDate>Mon, 25 Mar 2024 23:04:17 +0000</pubDate>
      <link>https://dev.to/tresorama/essential-cli-commands-2nn3</link>
      <guid>https://dev.to/tresorama/essential-cli-commands-2nn3</guid>
      <description>

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Crossposted on my blog&lt;/strong&gt;&lt;br&gt;
You can read it &lt;a href="https://jacopomarrone.com/blog/essentials-cli-commands" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Terminal vs Shells
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://jacopomarrone.com/blog/terminal-vs-shell" rel="noopener noreferrer"&gt;Terminal and shells are not the same things&lt;/a&gt;, even if they are used as synonymous.&lt;br&gt;&lt;br&gt;
Command must be written in the syntax expected by your shell.&lt;br&gt;&lt;br&gt;
This article is written for &lt;code&gt;zsh&lt;/code&gt; shell, the one I'm using in my Mac.&lt;/p&gt;
&lt;h2&gt;
  
  
  CLI General Reminders
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;File extensions are not necessary&lt;/strong&gt; for "doing things", extensions are used to mark which format the information is written in.
Outside CLI context, extensions are used by the OS to pick an appropriate Application and use it to open a file.
In CLI context they "are just the final part of the file name", so when you create a script file it's good practice to include an extension that indicate that is a script (&lt;code&gt;.sh&lt;/code&gt; &lt;code&gt;.command&lt;/code&gt; &lt;code&gt;.script&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Which folder you are in does not count&lt;/strong&gt;, but :

&lt;ul&gt;
&lt;li&gt;when referencing file path using a "relative" approach, the starting point is your current folder (knows as &lt;code&gt;cwd&lt;/code&gt;, current working directory)&lt;/li&gt;
&lt;li&gt;when referencing file path using a "relative" approach, it is irrelevant.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Commands
&lt;/h2&gt;

&lt;p&gt;Here is a list of essential CLI commands for your daily tasks...&lt;/p&gt;
&lt;h3&gt;
  
  
  Print absolute path of current directory
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# pwd (print working directory)&lt;/span&gt;
&lt;span class="nb"&gt;pwd&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Show files/folder of a directory
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# show files of current directory&lt;/span&gt;
&lt;span class="nb"&gt;ls&lt;/span&gt;
&lt;span class="c"&gt;# show files of other directory&lt;/span&gt;
&lt;span class="nb"&gt;ls &lt;/span&gt;path/to/directory
&lt;span class="c"&gt;# show as list (easily scannable)&lt;/span&gt;
&lt;span class="nb"&gt;ls&lt;/span&gt; &lt;span class="nt"&gt;-l&lt;/span&gt;
&lt;span class="c"&gt;# include hidden files&lt;/span&gt;
&lt;span class="nb"&gt;ls&lt;/span&gt; &lt;span class="nt"&gt;-a&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Show the file tree of a directory
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Install the "tree" command if on MacOS&lt;/span&gt;
brew &lt;span class="nb"&gt;install &lt;/span&gt;tree
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# show tree with depth level = 1&lt;/span&gt;
tree &lt;span class="nt"&gt;-L&lt;/span&gt; 1

&lt;span class="c"&gt;# output&lt;/span&gt;
&lt;span class="nb"&gt;.&lt;/span&gt;
├── Summer_Forest.mp4
├── dummy-assets
├── prove
├── text.txt
└── screenshot
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# show tree with depth level = 2&lt;/span&gt;
tree &lt;span class="nt"&gt;-L&lt;/span&gt; 2

&lt;span class="c"&gt;# output&lt;/span&gt;
&lt;span class="nb"&gt;.&lt;/span&gt;
├── Summer_Forest.mp4
├── dummy-assets
│   ├── artist
│   ├── images
│   └── travel
├── prove
│   ├── Schermata 2023-07-16 alle 20.33.14.png
│   ├── Schermata 2023-07-16 alle 20.33.22.png
│   ├── Schermata 2023-09-14 alle 21.56.02.png
│   ├── Schermata 2024-01-21 alle 17.56.25.png
│   ├── Schermata 2024-01-24 alle 21.57.38.png
│   ├── Schermata 2024-02-09 alle 18.39.27.png
│   ├── Schermata 2024-02-09 alle 18.39.54.png
│   ├── Schermata 2024-02-09 alle 18.55.26.png
│   ├── Schermata 2024-02-28 alle 10.39.45.png
│   ├── Schermata 2024-02-28 alle 13.06.00.png
│   ├── Schermata 2024-02-28 alle 14.41.22.png
│   ├── Schermata 2024-03-03 alle 16.29.49.png
│   ├── Schermata 2024-03-04 alle 17.11.15.png
│   ├── Schermata 2024-03-04 alle 18.05.51.png
│   ├── Schermata 2024-03-08 alle 17.50.21.png
│   ├── Schermata 2024-03-09 alle 15.36.57.png
│   └── Schermata 2024-03-11 alle 13.50.38.png
├── text.txt
└── screenshot
    ├── Schermata 2024-01-30 alle 17.28.04.png
    └── Schermata 2024-02-26 alle 14.52.17.png
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Go to a directory
&lt;/h3&gt;

&lt;p&gt;Change current directory with provided one&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# go to dir (named "dirName") that is child of current directory&lt;/span&gt;
&lt;span class="nb"&gt;cd &lt;/span&gt;dirName 
&lt;span class="c"&gt;# go to dir (named "dirName") knowing its absolute path&lt;/span&gt;
&lt;span class="nb"&gt;cd&lt;/span&gt; /absolute/path/to/dirName
&lt;span class="c"&gt;# go to parent directory&lt;/span&gt;
&lt;span class="nb"&gt;cd&lt;/span&gt; ..
&lt;span class="c"&gt;# go to home directory&lt;/span&gt;
&lt;span class="c"&gt;# in MacOS home directory is /Users/your-name&lt;/span&gt;
&lt;span class="nb"&gt;cd&lt;/span&gt; ~
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Create a directory
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# create a new directory named "dirName" as child of current dir&lt;/span&gt;
&lt;span class="nb"&gt;mkdir &lt;/span&gt;dirName
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Create a file
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# create a new file named "fileName" as child of current dir&lt;/span&gt;
&lt;span class="nb"&gt;touch &lt;/span&gt;fileName
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Edit a file with a text editor
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# with "nano" text editor&lt;/span&gt;
nano fileName.txt
&lt;span class="c"&gt;# with "vs code" text editor&lt;/span&gt;
code fileName.txt
&lt;span class="c"&gt;# with "vim" text editor&lt;/span&gt;
vi fileName.txt
&lt;span class="c"&gt;# with "micro text editor&lt;/span&gt;
micro fileName.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Open a file with the default app used by the OS
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# open a file named "fileName" with OS default app&lt;/span&gt;
open fileName.png
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Show in Finder/File Explorer a directory
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# show current dir (do not miss the dot)&lt;/span&gt;
open &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;span class="c"&gt;# show a dir using absolute path&lt;/span&gt;
open /abs/path/to/dir
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;I write articles mainly to help future myself or to help the growth of tools I use in my work.&lt;/p&gt;

&lt;p&gt;If this article was helpful to you leave a like.&lt;/p&gt;

&lt;p&gt;Would you like me to talk about a particular topic?&lt;br&gt;&lt;br&gt;
Tell me in the comments!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>cli</category>
      <category>beginners</category>
      <category>bash</category>
    </item>
    <item>
      <title>Terminal vs Shell</title>
      <dc:creator>Jacopo Marrone @tresorama</dc:creator>
      <pubDate>Mon, 25 Mar 2024 23:02:05 +0000</pubDate>
      <link>https://dev.to/tresorama/terminal-vs-shell-39jk</link>
      <guid>https://dev.to/tresorama/terminal-vs-shell-39jk</guid>
      <description>

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Crossposted on my blog&lt;/strong&gt;&lt;br&gt;
You can read it &lt;a href="https://jacopomarrone.com/blog/terminal-vs-shell" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;Terminal and Shell are not the same things but are commonly used interchangeably to refer to the the same concept: &lt;strong&gt;doing things with a CLI (command line interface).&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Which is the difference between Terminal and Shell?
&lt;/h2&gt;

&lt;p&gt;I like analogies to understand concepts, so when talking about Terminal and Shell these are what comes to my mind...&lt;/p&gt;

&lt;h3&gt;
  
  
  Analogy with VideoGames Emulator
&lt;/h3&gt;

&lt;p&gt;If you want to play old Pokemon games in 2024, you have 2 options&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Buy a Nintendo GameBoy Color/Advance and the game cartridge&lt;/li&gt;
&lt;li&gt;Download an Emulator software on your PC and download the game file (ROM)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Opting for the Emulator...&lt;/p&gt;

&lt;p&gt;You launch the Emulator, you decide which Console simulate and then you launch the game you want to play.&lt;br&gt;
Similarly, When you launch a Terminal, you decide which Shell execute and then launch your commands by typing with the keyboard.&lt;/p&gt;

&lt;p&gt;An Emulator can execute multiple Consoles.&lt;br&gt;
A Terminal can execute multiple Shells.&lt;/p&gt;

&lt;p&gt;If Consoles are &lt;code&gt;GameBoy Color&lt;/code&gt;, &lt;code&gt;GameBoy Advance&lt;/code&gt;...&lt;br&gt;&lt;br&gt;
Shells are &lt;code&gt;zsh&lt;/code&gt;, &lt;code&gt;bash&lt;/code&gt;...&lt;/p&gt;
&lt;h3&gt;
  
  
  Analogy with Node and PHP
&lt;/h3&gt;

&lt;p&gt;If you are familiar to &lt;strong&gt;Javascript&lt;/strong&gt; and &lt;strong&gt;Node.js&lt;/strong&gt; you know that you can "execute" js code by writing js code inside a file and then execute it by opening a Terminal and doing&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;node script.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;node&lt;/code&gt; is the executable that parse the &lt;code&gt;script.js&lt;/code&gt;, interprets it and executes it.&lt;/p&gt;

&lt;p&gt;Same things with &lt;strong&gt;PHP&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;php script.php
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;php&lt;/code&gt; is the executable that parse the &lt;code&gt;script.php&lt;/code&gt;, interprets it and executes it.&lt;/p&gt;

&lt;p&gt;Going back to Terminal vs Shell, you can think that when you do&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;'a text portion'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;under the hood this pseudo code happens&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;shell &lt;span class="s2"&gt;"echo 'a text portion'"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So the &lt;code&gt;shell&lt;/code&gt; (like &lt;code&gt;node&lt;/code&gt; and &lt;code&gt;php&lt;/code&gt; in previous example) interprets and execute the code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Common Shells
&lt;/h2&gt;

&lt;p&gt;Common shells in MacOS are &lt;code&gt;zsh&lt;/code&gt;, and &lt;code&gt;bash&lt;/code&gt;.&lt;br&gt;&lt;br&gt;
Other shells are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;sh&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;csh&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;dash&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ksh&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;tcsh&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Which shell I'm using right now?
&lt;/h2&gt;

&lt;p&gt;To check which shell is currently running you can run&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$0&lt;/span&gt;
&lt;span class="c"&gt;# output&lt;/span&gt;
zsh

&lt;span class="c"&gt;# not working? try these&lt;/span&gt;
ps &lt;span class="nt"&gt;-p&lt;/span&gt; &lt;span class="nv"&gt;$$&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Which shells are installed?
&lt;/h2&gt;

&lt;p&gt;To check which shells are installed you can run&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; /etc/shells

&lt;span class="c"&gt;# output&lt;/span&gt;

&lt;span class="c"&gt;# List of acceptable shells for chpass(1).&lt;/span&gt;
&lt;span class="c"&gt;# Ftpd will not allow users to connect who are not using&lt;/span&gt;
&lt;span class="c"&gt;# one of these shells.&lt;/span&gt;

/bin/bash
/bin/csh
/bin/dash
/bin/ksh
/bin/sh
/bin/tcsh
/bin/zsh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  How to change shell for current session?
&lt;/h2&gt;

&lt;p&gt;To change which shell is currently running you can run&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# launch a "bash" shell&lt;/span&gt;
bash

&lt;span class="c"&gt;# print current running shell&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$0&lt;/span&gt; 
&lt;span class="c"&gt;# bash&lt;/span&gt;

&lt;span class="c"&gt;# print default shell for current user&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$SHELL&lt;/span&gt;
&lt;span class="c"&gt;# /bin/zsh&lt;/span&gt;

&lt;span class="c"&gt;# exit shell&lt;/span&gt;
&lt;span class="nb"&gt;exit&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# launch a zsh shell&lt;/span&gt;
zsh

&lt;span class="c"&gt;# print current running shell&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$0&lt;/span&gt; 
&lt;span class="c"&gt;# zsh&lt;/span&gt;

&lt;span class="c"&gt;# print default shell for current user&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$SHELL&lt;/span&gt;
&lt;span class="c"&gt;# /bin/zsh&lt;/span&gt;

&lt;span class="c"&gt;# exit shell&lt;/span&gt;
&lt;span class="nb"&gt;exit&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you noted, this will not change the default shell for your user, but it will change the shell for the current CLI session only.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to check and change default shell?
&lt;/h2&gt;

&lt;p&gt;When you open the "Terminal" app on your OS, that programs launch the "shell" configured as default for your user.&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Every user has a default shell defined.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You can check which is the default shell for you user by running&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$SHELL&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

&lt;span class="c"&gt;# /bin/zsh&lt;/span&gt;

&lt;span class="c"&gt;# In my case the default is "zsh", &lt;/span&gt;
&lt;span class="c"&gt;# and the binary/executable path for "zsh" is /bin/zsh.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then list shells path that you can use with&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; /etc/shells

&lt;span class="c"&gt;# List of acceptable shells for chpass(1).&lt;/span&gt;
&lt;span class="c"&gt;# Ftpd will not allow users to connect who are not using&lt;/span&gt;
&lt;span class="c"&gt;# one of these shells.&lt;/span&gt;

/bin/bash
/bin/csh
/bin/dash
/bin/ksh
/bin/sh
/bin/tcsh
/bin/zsh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And update the default shell with&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# change to "sh" shell&lt;/span&gt;
chsh &lt;span class="nt"&gt;-s&lt;/span&gt; /bin/sh

&lt;span class="c"&gt;# or, change to "bash" shell&lt;/span&gt;
chsh &lt;span class="nt"&gt;-s&lt;/span&gt; /bin/bash
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;I write articles mainly to help future myself or to help the growth of tools I use in my work.&lt;/p&gt;

&lt;p&gt;If this article was helpful to you leave a like.&lt;/p&gt;

&lt;p&gt;Would you like me to talk about a particular topic?&lt;br&gt;&lt;br&gt;
Tell me in the comments !&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>cli</category>
      <category>bash</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Maybe you don't know that Javascript can conditionally import</title>
      <dc:creator>Jacopo Marrone @tresorama</dc:creator>
      <pubDate>Wed, 24 May 2023 15:05:56 +0000</pubDate>
      <link>https://dev.to/tresorama/javascript-dynamic-async-import-7oa</link>
      <guid>https://dev.to/tresorama/javascript-dynamic-async-import-7oa</guid>
      <description>&lt;p&gt;For a side project, I was creating a personal blog starter.&lt;br&gt;
Without going into details, it's a Next.js project that use SSG to create every pages at build time.&lt;br&gt;
You can decide "how and where" you write and store your articles.&lt;br&gt;
The choice is between these &lt;code&gt;datasources&lt;/code&gt; :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Flat File (version-controlled markdown file in a sub dir of the repo)&lt;/li&gt;
&lt;li&gt;Notion Database&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Both &lt;code&gt;datasource&lt;/code&gt; are coded as an object with a type signature shared by every &lt;code&gt;datasource&lt;/code&gt;, so that the view layer is decoupled from the real &lt;code&gt;datasource&lt;/code&gt; implementation.&lt;/p&gt;

&lt;p&gt;Both "flat-file" and "notion" strategies have code implementaion, this implementaion is located in different location inside the repo folder structure.&lt;br&gt;
In case you use "notion" strategies, it is not necessary that the code imports the "flat file" code becasue it will be never used, and viceversa.&lt;/p&gt;

&lt;p&gt;To solve this problem, at the beginning you must open a file and comment/uncomment a line of code, like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// 1. when notion is the choice&lt;/span&gt;
&lt;span class="c1"&gt;// import { flatFileDatasource as datasource } from './strategies/flat-file';&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;notionDatasource&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;datasource&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;./strategies/notion&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="nx"&gt;datasource&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// 2. when flat file is the choice&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;flatFileDatasource&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;datasource&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;./strategies/flat-file&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;// import { notionDatasource as datasource } from './strategies/notion';&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="nx"&gt;datasource&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;It works. But is not comfortable.&lt;/p&gt;

&lt;p&gt;What if I can conditionally import a module or an other ?!??&lt;br&gt;&lt;br&gt;
Well, Javascript covers this case.&lt;/p&gt;
&lt;h2&gt;
  
  
  Dynamic Import
&lt;/h2&gt;

&lt;p&gt;This syntax&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&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;something&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;./someplace&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;is known as &lt;code&gt;static import&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;But javascript has also a &lt;code&gt;dynamic and async import&lt;/code&gt; feature&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./someplace&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kr"&gt;module&lt;/span&gt;&lt;span class="o"&gt;=&amp;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="kr"&gt;module&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;that returns a promise with the imported module object.&lt;/p&gt;

&lt;p&gt;Of course when you export a promise, who imports it must await before utilizing its resolved value, so you must adjust some other code as well.&lt;/p&gt;

&lt;p&gt;Here is a generic example&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// file: ./fancy-lib.ts&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;getLib&lt;/span&gt;&lt;span class="p"&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="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;FancyLibType&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;today&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;monday&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;getLib&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="k"&gt;import&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./monday&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kr"&gt;module&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kr"&gt;module&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;today&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;friday&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;getLib&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="k"&gt;import&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./friday&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kr"&gt;module&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kr"&gt;module&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`No libraries for &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;today&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; day`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; 


&lt;span class="c1"&gt;// file: ./consumer-of-fancy-lib.ts&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;getLib&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;./fancy-lib&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;manipulation&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;myLib&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;getLib&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="c1"&gt;// ... rest of the code&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;Dynamic import lets you import modules based on conditions that are computed at runtime, opening the possibility to avoid loading unnecessary code.&lt;br&gt;&lt;br&gt;
Due to the nature of the feature, that utilizes Promise, some other code needs to be updated as async as well.  &lt;/p&gt;




&lt;p&gt;And you?&lt;br&gt;
Have you ever used dynamic import?&lt;br&gt;
Do you have a static alternative for conditional import? Feel free to share.&lt;/p&gt;




&lt;h2&gt;
  
  
  Resources
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import"&gt;MDN - import - static&lt;/a&gt;&lt;br&gt;&lt;br&gt;
&lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/import"&gt;MDN - import() - dynamic&lt;/a&gt;&lt;/p&gt;

</description>
      <category>frontend</category>
      <category>learning</category>
      <category>react</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Advanced Tailwind Syntax</title>
      <dc:creator>Jacopo Marrone @tresorama</dc:creator>
      <pubDate>Mon, 22 May 2023 14:31:06 +0000</pubDate>
      <link>https://dev.to/tresorama/advanced-tailwind-syntax-11bm</link>
      <guid>https://dev.to/tresorama/advanced-tailwind-syntax-11bm</guid>
      <description>&lt;p&gt;It's common to use Tailwind with classes like &lt;code&gt;m-4 bg-red-500&lt;/code&gt; that use the &lt;code&gt;theme&lt;/code&gt; tokens.&lt;br&gt;&lt;br&gt;
&lt;a href="https://tailwindcss.com/docs/installation"&gt;Tailwind Docs&lt;/a&gt; is well done and covers everything.&lt;/p&gt;



&lt;p&gt;But when you need to write CSS that doesn't use theme, you are using the tailwind syntax for &lt;strong&gt;arbitrary rules&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;This is when you can find this cheat sheet useful.&lt;/strong&gt;&lt;/p&gt;

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


&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
    &lt;a href="https://tailwind-syntax-examples.vercel.app/" rel="noopener noreferrer"&gt;
      tailwind-syntax-examples.vercel.app
    &lt;/a&gt;
&lt;/div&gt;





&lt;p&gt;Feel free to suggest something that is missing...&lt;/p&gt;

</description>
      <category>frontend</category>
      <category>learning</category>
      <category>react</category>
      <category>vue</category>
    </item>
    <item>
      <title>Advanced Tailwind Syntax - Old</title>
      <dc:creator>Jacopo Marrone @tresorama</dc:creator>
      <pubDate>Mon, 22 May 2023 02:07:20 +0000</pubDate>
      <link>https://dev.to/tresorama/tailwind-cheatsheet-for-arbitrary-values-1a04</link>
      <guid>https://dev.to/tresorama/tailwind-cheatsheet-for-arbitrary-values-1a04</guid>
      <description>&lt;p&gt;It's common to use Tailwind with classes like &lt;code&gt;m-4 bg-red-500&lt;/code&gt; that use the &lt;code&gt;theme&lt;/code&gt; tokens.&lt;br&gt;&lt;br&gt;
&lt;a href="https://tailwindcss.com/docs/installation"&gt;Tailwind Docs&lt;/a&gt; is well done and covers everything.&lt;/p&gt;



&lt;p&gt;But when you need to write CSS that doesn't use theme, you are using the tailwind syntax for &lt;strong&gt;arbitrary rules&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;This is when you can find this cheat sheet useful.&lt;/strong&gt;&lt;/p&gt;

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


&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
    &lt;a href="https://tailwind-syntax-examples.vercel.app/" rel="noopener noreferrer"&gt;
      tailwind-syntax-examples.vercel.app
    &lt;/a&gt;
&lt;/div&gt;





&lt;p&gt;Feel free to suggest something that is missing...&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Learning Vue as a React dev</title>
      <dc:creator>Jacopo Marrone @tresorama</dc:creator>
      <pubDate>Wed, 17 May 2023 01:47:09 +0000</pubDate>
      <link>https://dev.to/tresorama/learning-vue-as-a-react-dev-1m8g</link>
      <guid>https://dev.to/tresorama/learning-vue-as-a-react-dev-1m8g</guid>
      <description>&lt;p&gt;I work daily with React. In recent days I decided to try Vue for the first time.&lt;br&gt;&lt;br&gt;
I enjoyed the experience, so I decided to share my thoughts.&lt;/p&gt;
&lt;h2&gt;
  
  
  Frontend Framework
&lt;/h2&gt;

&lt;p&gt;Do you know &lt;code&gt;Create React App&lt;/code&gt;? &lt;code&gt;Class Components&lt;/code&gt;? &lt;code&gt;React Hooks&lt;/code&gt;? &lt;code&gt;Next.js&lt;/code&gt;?&lt;/p&gt;

&lt;p&gt;Great, so you know why their Vue equivalent exists.&lt;/p&gt;

&lt;p&gt;To scaffold a project with a lot of DX stuff already configured, React has &lt;code&gt;Create React App&lt;/code&gt;, Vue has &lt;code&gt;Vue CLI&lt;/code&gt;. Recently, both &lt;code&gt;Create React App&lt;/code&gt; and &lt;code&gt;Vue CLI&lt;/code&gt; are in maintenance mode. Now is recommended to use &lt;code&gt;Vite&lt;/code&gt; for both, unless you use a meta framework (Next.js and Nuxt).&lt;/p&gt;

&lt;p&gt;React has &lt;code&gt;Class Components&lt;/code&gt; and Vue has &lt;code&gt;Options API&lt;/code&gt;. React has &lt;code&gt;React Hooks&lt;/code&gt; and Vue &lt;code&gt;Composition API&lt;/code&gt;. React has &lt;code&gt;Next.js&lt;/code&gt; and Vue &lt;code&gt;Nuxt.js&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  Key differences, React vs Vue
&lt;/h2&gt;
&lt;h3&gt;
  
  
  The ecosystem
&lt;/h3&gt;

&lt;p&gt;React is a library, Vue is a framework.&lt;/p&gt;

&lt;p&gt;This means that Vue has a wider set of official tools, integrated as a whole "framework". React, on the other end, need to be extended by third-party tools.&lt;/p&gt;

&lt;p&gt;In Vue, the core team defines the way, in React, the community drives everything.&lt;br&gt;&lt;br&gt;
I'm not saying that Vue doesn't have an active community, but that Vue team guides a lot more than React one.&lt;/p&gt;

&lt;p&gt;What do I mean by "ecosystem"?&lt;/p&gt;

&lt;p&gt;Think about these common "parts" of a frontend app:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Client Side Routing, which handles the navigation between different pages of your app, even if the browser never redirects actually (the core of a SPA, Single Page Application)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Global State Management, which handles the share of state between multiple components without passing props down to every level of the app tree.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;How do you solve them?&lt;/p&gt;

&lt;p&gt;The Vue team authored Vuex and Pinia for Global State Management, and Vue Router for Client Side Routing.&lt;/p&gt;

&lt;p&gt;React has no official tools, but this means that a lot of third-party good libraries have emerged over time to fill the gap. Like Redux for Global State Management and React Router or Reach Router for Client Side Routing.&lt;/p&gt;

&lt;p&gt;Think about this as ...&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;React gives the world an essential building block for handling reactivity in a Frontend App and, but has no official way to structure the rest of the app, leaving this duty to the community.&lt;br&gt;&lt;br&gt;
Vue instead gives the reactivity system and also a toolbelt with a solid opinion on how to handle everything, so there is an official package for every common problem.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;No best or worst.&lt;br&gt;&lt;br&gt;
Both are great declarative libraries, with a good DX.&lt;br&gt;&lt;br&gt;
Don't be a blind fanboy :)&lt;/p&gt;
&lt;h3&gt;
  
  
  The render runs only once
&lt;/h3&gt;

&lt;p&gt;In react, a render function or a function component re-runs after every state changes.&lt;br&gt;&lt;br&gt;
React compare the result with the current DOM state and decide if to "reconcile" or not.&lt;/p&gt;

&lt;p&gt;Instead, in Vue, the template (the render function equivalent) is run only once.&lt;br&gt;&lt;br&gt;
I don't know much about how internal works in Vue, but if you put a console.log inside the script portion of a template it will run only once.&lt;/p&gt;
&lt;h3&gt;
  
  
  No need for dependencies array
&lt;/h3&gt;

&lt;p&gt;Vue reactivity system is different from React one.&lt;/p&gt;

&lt;p&gt;In React you must optimize your code using &lt;code&gt;useMemo&lt;/code&gt; , &lt;code&gt;useCallback&lt;/code&gt; and other things to avoid unnecessary computation and bugs.&lt;br&gt;&lt;br&gt;
I'm referring mainly to the dependencies array.&lt;/p&gt;

&lt;p&gt;In Vue all these duties are in charge of the library.&lt;br&gt;&lt;br&gt;
Vue takes care of analyzing and understanding when a piece of code, that depends on some reactive values needs to be recalculated.&lt;br&gt;&lt;br&gt;
No need to define dependencies.&lt;/p&gt;

&lt;p&gt;Beginners could find this a winning point in favor of Vue.&lt;/p&gt;
&lt;h2&gt;
  
  
  A brief history of Vue
&lt;/h2&gt;
&lt;h3&gt;
  
  
  History
&lt;/h3&gt;

&lt;p&gt;Vue.js was first released in February 2014 by ex-Google engineer Evan You.&lt;br&gt;&lt;br&gt;
It is an open-source progressive JavaScript framework used for building user interfaces (UIs) and single-page applications.&lt;/p&gt;

&lt;p&gt;The Options API was the original API for Vue.js.&lt;br&gt;&lt;br&gt;
The Composition API was introduced later in Vue 3.0, which was released in September 2020.&lt;/p&gt;
&lt;h3&gt;
  
  
  Evolution: Options API and Composition API
&lt;/h3&gt;

&lt;p&gt;Let's be honest, 99,9% of React nowadays is written in hook style. But imagine that in your work you inherit a legacy project written in Class Components... better you don't feel lost.&lt;/p&gt;

&lt;p&gt;So a React beginner should spend a little bit of time on Class Components even if the standard way of writing React is with Hooks.&lt;br&gt;&lt;br&gt;
The same with Vue.&lt;br&gt;&lt;br&gt;
Don't you agree? Let me know it.&lt;/p&gt;

&lt;p&gt;Vue initial API is now called "Options API" and is considered legacy.&lt;br&gt;&lt;br&gt;
Vue 3 introduced a new style of writing Vue, that is now the standard,and it is known as "Composition API".&lt;/p&gt;

&lt;p&gt;React has had the same evolution, with React Hooks as successor of Class Components.&lt;/p&gt;
&lt;h4&gt;
  
  
  Compare Vue and React
&lt;/h4&gt;

&lt;p&gt;Take this React class component&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;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Counter&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Component&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="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// decalare local state&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;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;count&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="c1"&gt;// bind "this" to event handlers&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;handleIncrementClick&lt;/span&gt; &lt;span class="o"&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;handleIncrementClick&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;bind&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="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;handleDecrementClick&lt;/span&gt; &lt;span class="o"&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;handleDecrementClick&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;bind&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="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;// define event handlers&lt;/span&gt;
  &lt;span class="nf"&gt;handleIncrementClick&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="nf"&gt;setState&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;count&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;state&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;handleDecrementClick&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="nf"&gt;setState&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;count&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;state&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="c1"&gt;// render the template&lt;/span&gt;
  &lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;h1&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Counter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&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;/h1&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;handleIncrementClick&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;+&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;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="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;handleDecrementClick&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;-&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this class component, we define a &lt;code&gt;state&lt;/code&gt; object that includes a &lt;code&gt;count&lt;/code&gt; property, which will hold the current value of the counter. We also define two methods, &lt;code&gt;handleIncrementClick&lt;/code&gt; and &lt;code&gt;handleDecrementClick&lt;/code&gt;, which increment and decrement the count property of the state object, respectively.&lt;/p&gt;

&lt;p&gt;In the render method, we display the current value of count in an h1 element, and we include two buttons that call the &lt;code&gt;handleIncrementClick&lt;/code&gt; and &lt;code&gt;handleDecrementClick&lt;/code&gt; methods, respectively, when clicked. When either button is clicked, the count property of the state object is updated, which triggers a re-render of the component and updates the displayed value of the counter.&lt;/p&gt;

&lt;p&gt;This is the Vue counterpart in Options API&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;template&amp;gt;
  &amp;lt;div&amp;gt;
    &amp;lt;h1&amp;gt;Counter: {{ count }}&amp;lt;/h1&amp;gt;
    &amp;lt;button @click="incrementCount"&amp;gt;+&amp;lt;/button&amp;gt;
    &amp;lt;button @click="decrementCount"&amp;gt;-&amp;lt;/button&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;/template&amp;gt;

&amp;lt;script&amp;gt;
export default {
  data() {
    return {
      count: 0
    }
  },
  methods: {
    incrementCount() {
      this.count++;
    },
    decrementCount() {
      this.count--;
    }
  }
}
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;data&lt;/code&gt; function must return an object that is the local &lt;code&gt;state&lt;/code&gt;.&lt;br&gt;&lt;br&gt;
Under &lt;code&gt;methods&lt;/code&gt;, you defined &lt;code&gt;incrementCount&lt;/code&gt; and &lt;code&gt;decrementCount&lt;/code&gt;. Vue under the hood takes care of "binding" the &lt;code&gt;this&lt;/code&gt; instance to "methods" handlers, so we don't have to. In addition, updating the local state is done in a mutable fashion, instead of React's immutable.&lt;br&gt;&lt;br&gt;
Vue uses Proxy under the hood, so, in reality, you are not mutating the "real" state object but the proxied one. But from a developer's point of vue view it's less code.&lt;/p&gt;

&lt;p&gt;But the overall component code is almost identical.&lt;/p&gt;

&lt;p&gt;Ok, this was Class Components vs Options API.&lt;br&gt;&lt;br&gt;
Now let's take a look to React Hook vs Composition API.&lt;/p&gt;

&lt;p&gt;React&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Counter&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="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="nx"&gt;React&lt;/span&gt;&lt;span class="p"&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;incrementCount&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;prev&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;prev&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;decrementCount&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;prev&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;prev&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="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Counter: &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;incrementCount&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;+&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;decrementCount&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;-&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Vue Composition API&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;script setup&amp;gt;
import {ref} from 'vue';

const count = ref(0);
const incrementCount = () =&amp;gt; count.value++;
const decrementCount = () =&amp;gt; count.value--;
&amp;lt;/script&amp;gt;

&amp;lt;template&amp;gt;
  &amp;lt;div&amp;gt;
    &amp;lt;h1&amp;gt;Counter: {{count}}&amp;lt;/h1&amp;gt;
    &amp;lt;button @click="incrementCount"&amp;gt;+&amp;lt;/button&amp;gt;
    &amp;lt;button @click="decrementCount"&amp;gt;-&amp;lt;/button&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;/template&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;They look similar.&lt;/p&gt;

&lt;p&gt;For a good description of the entire reactivity system of Vue read &lt;a href="https://vuejs.org/guide/essentials/template-syntax.html"&gt;Template Syntax&lt;/a&gt; and &lt;a href="https://vuejs.org/guide/essentials/reactivity-fundamentals.html"&gt;Reactivity Fundamentals&lt;/a&gt;. This is not a tutorial, so take a look there if something is not clear...&lt;/p&gt;

&lt;h2&gt;
  
  
  The Vue way
&lt;/h2&gt;

&lt;p&gt;It's time to explore some Vue distinctive stuff, that makes it different from React.&lt;/p&gt;

&lt;h3&gt;
  
  
  v-model
&lt;/h3&gt;

&lt;p&gt;Take this React code that renders an input&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;InputComponent&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="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;inputValue&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setInputValue&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleChange&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setInputValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;
        &lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
        &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;inputValue&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="nx"&gt;onChange&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;handleChange&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;You&lt;/span&gt; &lt;span class="na"&gt;entered&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;inputValue&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;/p&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;... and look it in Vue with Composition API&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;script setup&amp;gt;
import {ref} from 'vue';
const inputValue = ref('');
&amp;lt;/script&amp;gt;

&amp;lt;template&amp;gt;
  &amp;lt;div&amp;gt;
    &amp;lt;input type="text" v-model="inputValue" /&amp;gt;
    &amp;lt;p&amp;gt;You entered: {{ inputValue }}&amp;lt;/p&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;/template&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;... and Options API&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;template&amp;gt;
  &amp;lt;div&amp;gt;
    &amp;lt;input type="text" v-model="inputValue" /&amp;gt;
    &amp;lt;p&amp;gt;You entered: {{ inputValue }}&amp;lt;/p&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;/template&amp;gt;

&amp;lt;script&amp;gt;
export default {
  data() {
    return {
      inputValue: ''
    }
  },
}
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A lot less code.&lt;br&gt;&lt;br&gt;
Great, don't you think???&lt;/p&gt;

&lt;p&gt;&lt;code&gt;v-model&lt;/code&gt; does all the boring stuff of the Two-Way Data Binding between template and component instance.&lt;/p&gt;

&lt;p&gt;This is a great DX improvement of Vue, when compared to React.&lt;/p&gt;

&lt;p&gt;Can I use the React way? Yes, in Vue you can use the React "way" if you want.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;script setup&amp;gt;
  const inputValue = ref('');
&amp;lt;/script&amp;gt;

&amp;lt;input
  :value="inputValue"
  @input="(event) =&amp;gt; inputValue.value = event.target.value"
/&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  computed
&lt;/h3&gt;

&lt;p&gt;Computed data, is data that is derived from the state, and should be automatically recalculated on every state update.&lt;/p&gt;

&lt;p&gt;Let's augment the Counter example with a &lt;code&gt;doubledCount&lt;/code&gt; derived value.&lt;/p&gt;

&lt;p&gt;In React&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Counter&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="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="nx"&gt;React&lt;/span&gt;&lt;span class="p"&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;doubledCount&lt;/span&gt; &lt;span class="o"&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;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="c1"&gt;// here a useMemo version if computation is expensive&lt;/span&gt;
  &lt;span class="c1"&gt;// const doubledCount = useMemo(() =&amp;gt; count * 2, [count]);&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;incrementCount&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;prev&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;prev&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;decrementCount&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;prev&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;prev&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="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;h1&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;Count&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h1&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;h1&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Doubled&lt;/span&gt; &lt;span class="na"&gt;Count&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;doubledCount&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;/h1&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;incrementCount&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Increment&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;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;decrementCount&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;Decrement&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;...in Vue Composition API&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;script setup&amp;gt;
import {ref, computed} from 'vue';
const count = ref(0);
const doubledCount = computed(() =&amp;gt; count.value * 2); 
&amp;lt;/script&amp;gt;

&amp;lt;template&amp;gt;
  &amp;lt;div&amp;gt;
    &amp;lt;h1&amp;gt;Count: {{ count }}&amp;lt;/h1&amp;gt;
    &amp;lt;h1&amp;gt;Doubled Count: {{ doubledCount }}&amp;lt;/h1&amp;gt;
    &amp;lt;button @click="incrementCount"&amp;gt;Increment&amp;lt;/button&amp;gt;
    &amp;lt;button @click="decrementCount"&amp;gt;Decrement&amp;lt;/button&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;/template&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;... and Options API&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;template&amp;gt;
  &amp;lt;div&amp;gt;
    &amp;lt;h1&amp;gt;Count: {{ count }}&amp;lt;/h1&amp;gt;
    &amp;lt;h1&amp;gt;Doubled Count: {{ doubledCount }}&amp;lt;/h1&amp;gt;
    &amp;lt;button @click="incrementCount"&amp;gt;Increment&amp;lt;/button&amp;gt;
    &amp;lt;button @click="decrementCount"&amp;gt;Decrement&amp;lt;/button&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;/template&amp;gt;

&amp;lt;script&amp;gt;
export default {
  data() {
    return {
      count: 0
    }
  },
  computed: {
    doubledCount() {
      return this.count * 2;
    }
  },
  methods: {
    incrementCount() {
      this.count++;
    },
    decrementCount() {
      this.count--;
    }
  }
}
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can think of "computed" as useMemo without dependency.&lt;br&gt;&lt;br&gt;
Not so much difference between React and Vue here.&lt;/p&gt;
&lt;h3&gt;
  
  
  Emitting events
&lt;/h3&gt;

&lt;p&gt;Think about a parent component, that renders a child component and wants to be notified when the child is clicked.&lt;/p&gt;

&lt;p&gt;In React you "pass" down a function via props.&lt;br&gt;
&lt;/p&gt;

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

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ChildComponent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;onClick&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Click me!&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ParentComponent&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleChildClick&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Child is clicked!!!!!&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Hello, world!&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ChildComponent&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;handleChildClick&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;in Vue instead you "emit" an event (like in native DOM elements) from the child component and "listen" to that event in the parent component.&lt;/p&gt;

&lt;p&gt;This is Vue Composition API&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;script setup&amp;gt;
import { defineEmits } from 'vue';

// define all event that this component can emit...
const emits = defineEmits(['clicked']);

const handleClick = () =&amp;gt; {
  emits('clicked');
}
&amp;lt;/script&amp;gt;

&amp;lt;template&amp;gt;
    &amp;lt;button @click="handleClick"&amp;gt;Click me!&amp;lt;/button&amp;gt;
&amp;lt;/template&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;script setup&amp;gt;
import ChildComponent from './ChildComponent.vue';

const handleChildClick = () =&amp;gt; {
  console.log('Child is clicked!!!!!');
}
&amp;lt;/script&amp;gt;

&amp;lt;template&amp;gt;
 &amp;lt;div&amp;gt;
    &amp;lt;h1&amp;gt;Hello, world!&amp;lt;/h1&amp;gt;
    &amp;lt;ChildComponent @clicked="handleChildClicked" /&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;/template&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;... and Options API&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;template&amp;gt;
  &amp;lt;div&amp;gt;
    &amp;lt;h1&amp;gt;Hello, world!&amp;lt;/h1&amp;gt;
    &amp;lt;ChildComponent @clicked="handleChildClicked" /&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;/template&amp;gt;

&amp;lt;script&amp;gt;
import ChildComponent from './ChildComponent.vue';

export default {
  name: "ParentComponent",
  // 
  // this registration of "components" is required 
  // before using a child component with Options API.
  components: {
    ChildComponent
  },
  methods: {
    handleChildClicked() {
      console.log('Hello');
    }
  }
}
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;template&amp;gt;
  &amp;lt;button @click="handleClick"&amp;gt;Click me!&amp;lt;/button&amp;gt;
&amp;lt;/template&amp;gt;

&amp;lt;script&amp;gt;
export default {
  name: "ChildComponent",
  methods: {
    handleClick() {
      this.$emit('clicked');
    }
  }
}
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The idea of emitting an event has the advantage that from the ChildComponent code there is no need to check if his parent has provided a function or not (like you would do in react when the "onClick" prop is optional).&lt;br&gt;&lt;br&gt;
The child emits the event anyway, and if someone is listening to it will be notified.&lt;/p&gt;

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

&lt;p&gt;I started learning Vue with Options API, founding it a bit verbose compared to React Hooks.&lt;br&gt;&lt;br&gt;
But when tried Composition API I felt at home.&lt;br&gt;&lt;br&gt;
The code is readable and without a "class-like" boilerplate, and the overall experience is great.&lt;/p&gt;

&lt;p&gt;Vue has some "magic", that makes code easier to read.&lt;br&gt;&lt;br&gt;
The only downside is that it feels weird to write js code inside quotes like it was a string as happens in HTML attributes.&lt;/p&gt;




&lt;p&gt;And you?&lt;br&gt;&lt;br&gt;
What do you think about Vue?&lt;/p&gt;

&lt;p&gt;Do you prefer it over React?&lt;br&gt;&lt;br&gt;
Why?&lt;/p&gt;

</description>
      <category>react</category>
      <category>vue</category>
      <category>frontend</category>
      <category>learning</category>
    </item>
    <item>
      <title>Publish a Typescript React library to NPM in a monorepo</title>
      <dc:creator>Jacopo Marrone @tresorama</dc:creator>
      <pubDate>Sat, 21 Jan 2023 05:23:20 +0000</pubDate>
      <link>https://dev.to/tresorama/publish-a-typescript-react-library-to-npm-in-a-monorepo-1ah1</link>
      <guid>https://dev.to/tresorama/publish-a-typescript-react-library-to-npm-in-a-monorepo-1ah1</guid>
      <description>

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Crossposted on my blog&lt;/strong&gt;&lt;br&gt;
You can read &lt;a href="https://jacopomarrone.com/blog/publish-a-typescript-react-library-to-npm-in-a-monorepo" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;In this blog post we create a small React library and publish it to NPM.&lt;br&gt;&lt;br&gt;
We'll go through all steps required to do that.&lt;br&gt;&lt;br&gt;
Let's begin.  &lt;/p&gt;
&lt;h2&gt;
  
  
  Overview
&lt;/h2&gt;

&lt;p&gt;The library we will publish (&lt;code&gt;package&lt;/code&gt; from now on) is written in Typescript, bundled with &lt;code&gt;tsup&lt;/code&gt;, versioned and published with &lt;code&gt;changeset&lt;/code&gt;.  &lt;/p&gt;

&lt;p&gt;To test the package we create one example app with &lt;code&gt;Next.js&lt;/code&gt; and one with &lt;code&gt;Vite&lt;/code&gt;.&lt;br&gt;&lt;br&gt;
To better manage these three apps (our package + Next.js demo + Vite demo) we store everything in a monorepo, using &lt;code&gt;turborepo&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;
  
  
  The Package
&lt;/h3&gt;

&lt;p&gt;It will be named &lt;code&gt;use-last-visit-date&lt;/code&gt; and will contain a React hook used to:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Retrieve date of last visit, that was previously saved to localStorage.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;
  
  
  Tutorial
&lt;/h2&gt;
&lt;h3&gt;
  
  
  1. Create a monorepo
&lt;/h3&gt;

&lt;p&gt;This guide will not cover how a monorepo works, if this concept is new to you can read a little about it to get the idea.  &lt;/p&gt;

&lt;p&gt;If you want to skip that, you should know that for this guide i opted to monorepo only to be able to have the package itself and demo apps in the same codebase.&lt;br&gt;&lt;br&gt;
Otherwise i should have created 3 separate repo.&lt;/p&gt;

&lt;p&gt;Let's go!&lt;/p&gt;
&lt;h4&gt;
  
  
  Setup
&lt;/h4&gt;

&lt;p&gt;Tool used: &lt;code&gt;turborepo&lt;/code&gt;, &lt;code&gt;pnpm&lt;/code&gt;&lt;br&gt;&lt;br&gt;
To create a new monorepo, use &lt;code&gt;create-turbo&lt;/code&gt; and follow the prompt.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;NOTE:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
If you don'have &lt;code&gt;pnpm&lt;/code&gt; installed you can install it following &lt;a href="https://pnpm.io/installation" rel="noopener noreferrer"&gt;installation guide&lt;/a&gt;&lt;br&gt;&lt;br&gt;
You can also use &lt;code&gt;yarn&lt;/code&gt; or &lt;code&gt;npm&lt;/code&gt; if you want.&lt;br&gt;
&lt;/p&gt;


&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# create a monorepo&lt;/span&gt;
npx create-turbo@latest

&lt;span class="c"&gt;# answers&lt;/span&gt;
? Where would you like to create your turborepo? ./use-last-visit-date
? Which package manager &lt;span class="k"&gt;do &lt;/span&gt;you want to use? pnpm
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Turborepo will init the monorepo and print&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; Created a new turborepo with the following:

 - apps/web: Next.js with TypeScript
 - apps/docs: Next.js with TypeScript
 - packages/ui: Shared React component library
 - packages/eslint-config-custom: Shared configuration &lt;span class="o"&gt;(&lt;/span&gt;ESLint&lt;span class="o"&gt;)&lt;/span&gt;
 - packages/tsconfig: Shared TypeScript &lt;span class="sb"&gt;`&lt;/span&gt;tsconfig.json&lt;span class="sb"&gt;`&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; Success! Created a new Turborepo at &lt;span class="s2"&gt;"use-last-visit-date"&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Good to know
&lt;/h4&gt;

&lt;p&gt;&lt;code&gt;turborepo&lt;/code&gt; expose an executable &lt;code&gt;turbo&lt;/code&gt; that can fire a script in each workspace with a specific name.&lt;br&gt;&lt;br&gt;
For instance, running &lt;code&gt;turbo build&lt;/code&gt;  from root of monorepo will execute &lt;code&gt;build&lt;/code&gt; script in every workspace.&lt;br&gt;&lt;br&gt;
If a workspace hasn't a &lt;code&gt;build&lt;/code&gt; script, that workspace will be ignored.  &lt;/p&gt;

&lt;p&gt;In which order they are executed ?&lt;/p&gt;

&lt;p&gt;&lt;code&gt;turbo.json&lt;/code&gt; is the file where this configuration takes place.&lt;br&gt;&lt;br&gt;
Default setting will be enough for this guide, but i encourage you to read &lt;a href="https://turbo.build/repo/docs/core-concepts/monorepos/running-tasks" rel="noopener noreferrer"&gt;documentation&lt;/a&gt; later on.&lt;/p&gt;
&lt;h4&gt;
  
  
  Clean up
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Rename root &lt;code&gt;package.json&lt;/code&gt; &lt;code&gt;name&lt;/code&gt; to "root-monorepo" to avoid collision with package we are going to create.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Delete &lt;code&gt;apps/docs&lt;/code&gt; directory, we'll not use it&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;
  
  
  2. Create package workspace
&lt;/h3&gt;

&lt;p&gt;To create our package run :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# go to root of the monorepo&lt;/span&gt;
&lt;span class="nb"&gt;cd&lt;/span&gt; ./use-last-visit-date

&lt;span class="c"&gt;# create package directory&lt;/span&gt;
&lt;span class="nb"&gt;mkdir &lt;/span&gt;packages/use-last-visit-date
&lt;span class="nb"&gt;cd &lt;/span&gt;pacakges/use-last-visit-date

&lt;span class="c"&gt;# init the package with pnpm&lt;/span&gt;
pnpm init

&lt;span class="c"&gt;# install needed dev dependencies&lt;/span&gt;
pnpm add &lt;span class="nt"&gt;-D&lt;/span&gt; react react-dom @types/react @types/react-dom
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Add tsconfig
&lt;/h4&gt;

&lt;p&gt;We are using typescript so we need a &lt;code&gt;tsconfig&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;Fortunately, &lt;code&gt;turborepo&lt;/code&gt; already created a shared tsconfig internal package for us.&lt;br&gt;&lt;br&gt;
Inside there are various configuraion ready to be extended.&lt;br&gt;&lt;br&gt;
This is one of the beauties of using a tool like &lt;code&gt;turborepo&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Add &lt;code&gt;tsconfig&lt;/code&gt; as a dev dependency&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;# in packages/use-last-visit-date/package.json
&lt;span class="err"&gt;
&lt;/span&gt;"devDependencies": {
&lt;span class="gi"&gt;+  "tsconfig": "workspace:*",
&lt;/span&gt;}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Reinstall dependencies in whole monorepo&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pnpm &lt;span class="nb"&gt;install&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create a &lt;code&gt;tsconfig.json&lt;/code&gt; in &lt;code&gt;packages/use-last-visit-date&lt;/code&gt; with this content&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"extends"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"tsconfig/base.json"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"include"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"."&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"exclude"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"dist"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"node_modules"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"compilerOptions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"lib"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"dom"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"dom.iterable"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"esnext"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

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

&lt;/div&gt;



&lt;h4&gt;
  
  
  Write code
&lt;/h4&gt;

&lt;p&gt;Create the file which will contain our code&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# run this from packages/use-last-visit-date&lt;/span&gt;
&lt;span class="nb"&gt;touch&lt;/span&gt; ./index.ts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and fill with&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&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="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;storage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;last-visit-date&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;save&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;localStorage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;storage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="na"&gt;retrieve&lt;/span&gt;&lt;span class="p"&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="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;localStorage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;storage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="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;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;useLastVisitDate&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="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;lastVisitDate&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setLastVisitDate&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// On page load retrieve the last visit date if exists&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;storage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;retrieve&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nf"&gt;setLastVisitDate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[]);&lt;/span&gt;

  &lt;span class="c1"&gt;// On page close save current date&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handler&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;currentDate&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;Date&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;toISOString&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
      &lt;span class="nx"&gt;storage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;currentDate&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;beforeunload&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;handler&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;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;removeEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;beforeunload&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;handler&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="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;lastVisitDate&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;Then update which file will be exported by opening &lt;code&gt;packages/use-last-visit-date/package.json&lt;/code&gt; and&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;&lt;span class="gd"&gt;- "main": "index.js",
&lt;/span&gt;&lt;span class="gi"&gt;+ "main": "./index.ts",
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It's time to test our code in a real react app.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Create demo app workspace - Next
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;turborepo&lt;/code&gt; has already created a Next.js app in &lt;code&gt;apps/web&lt;/code&gt; so there is no need to do it.&lt;/p&gt;

&lt;p&gt;Because later on we will create also a Vite app, let's add a better name to this Next.js app.&lt;br&gt;&lt;br&gt;
Rename &lt;code&gt;apps/web&lt;/code&gt; dir to &lt;code&gt;apps/next&lt;/code&gt; and update &lt;code&gt;apps/next/package.json&lt;/code&gt; :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;&lt;span class="gd"&gt;- "name": "web",
&lt;/span&gt;&lt;span class="gi"&gt;+ "name": "next",
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then consume the &lt;code&gt;useLastVisitDate&lt;/code&gt; hook in &lt;code&gt;pages/index.tsx&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;formatDate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;date&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;Date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toLocaleString&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="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Page&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;lastVisitDate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useLastVisitDate&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;lastVisitDate&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hello, it's first time you visit us !&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;lastVisitDate&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="s2"&gt;`Last Visit: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nf"&gt;formatDate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;lastVisitDate&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But this will throw an error because &lt;code&gt;useLastVisitDate&lt;/code&gt; is not defined, and it's correct because we haven't imported it yet.  &lt;/p&gt;

&lt;p&gt;Before we can import it we must add the &lt;code&gt;use-last-visit-date&lt;/code&gt; to dependencies of &lt;code&gt;apps/next&lt;/code&gt;.&lt;br&gt;&lt;br&gt;
So update &lt;code&gt;apps/next/package.json&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;"dependencies": {
&lt;span class="gd"&gt;-  "ui": "workspace:*"
&lt;/span&gt;&lt;span class="gi"&gt;+  "use-last-visit-date": "workspace:*"
&lt;/span&gt;}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and tell pnpm to "refresh" monorepo dependencies by running&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# is not important from "where" you run this command&lt;/span&gt;
pnpm &lt;span class="nb"&gt;install&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now you can import the hook in &lt;code&gt;pages/index.tsx&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Add at the top&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;useLastVisitDate&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;use-last-visit-date&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;and errors should disappears.  &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;NOTE:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
If this is not happening, try Restarting TS server in your code editor.  &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Now it's time to test if it's working.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# run this from apps/next&lt;/span&gt;
pnpm dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And open &lt;a href="http://localhost:3000" rel="noopener noreferrer"&gt;http://localhost:3000&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;You should see&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Hello, it's first time you visit us !
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then refresh the page and text should be changed to&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Last Visit: ......
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  4. Create demo app workspace - Vite
&lt;/h3&gt;

&lt;p&gt;Move with shell to root of monorepo and&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# go to apps dir&lt;/span&gt;
&lt;span class="nb"&gt;cd &lt;/span&gt;apps

&lt;span class="c"&gt;# create a vite workspace&lt;/span&gt;
pnpm create vite vite-react &lt;span class="nt"&gt;--template&lt;/span&gt; react-ts

&lt;span class="c"&gt;# install dependencies&lt;/span&gt;
pnpm &lt;span class="nb"&gt;install&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Then consume the &lt;code&gt;useLastVisitDate&lt;/code&gt; hook in &lt;code&gt;src/App.tsx&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;formatDate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;date&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;Date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toLocaleString&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="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Page&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;lastVisitDate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useLastVisitDate&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;lastVisitDate&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hello, it's first time you visit us !&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;lastVisitDate&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="s2"&gt;`Last Visit: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nf"&gt;formatDate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;lastVisitDate&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But this will throw an error because &lt;code&gt;useLastVisitDate&lt;/code&gt; is not defined, and it's correct because we haven't imported it yet.  &lt;/p&gt;

&lt;p&gt;Before we can import it we must add the &lt;code&gt;use-last-visit-date&lt;/code&gt; to dependencies of &lt;code&gt;apps/vite-react&lt;/code&gt;.&lt;br&gt;&lt;br&gt;
So update &lt;code&gt;apps/vite-react/package.json&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;"dependencies": {
  ...other-deps,
&lt;span class="gi"&gt;+  "use-last-visit-date": "workspace:*"
&lt;/span&gt;}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and tell pnpm to "refresh" monorepo dependencies by running&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# is not important from "where" you run this command&lt;/span&gt;
pnpm &lt;span class="nb"&gt;install&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now you can import the hook in &lt;code&gt;src/App.tsx&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Add at the top&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;useLastVisitDate&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;use-last-visit-date&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;and errors should disappears.  &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;NOTE:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
If this is not happening, try Restarting TS server in your code editor.  &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Now it's time to test if it's working.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# run this from apps/vite-react&lt;/span&gt;
pnpm dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And open &lt;a href="http://localhost:5173" rel="noopener noreferrer"&gt;http://localhost:5173&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;You should see&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Hello, it's first time you visit us !
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then refresh the page and text should be changed to&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Last Visit: ......
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  5. Time to publish
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Overview
&lt;/h4&gt;

&lt;p&gt;Now, &lt;code&gt;use-last-visit-date&lt;/code&gt; is an internal packages, it's written in Typescript and it works because Next.js app and Vite app take care of compiling the code to js.&lt;br&gt;&lt;br&gt;
But our code should run also if these assumptions are not in place.  &lt;/p&gt;

&lt;p&gt;We need to compile to js.&lt;br&gt;&lt;br&gt;
Then we can publish to NPM.  &lt;/p&gt;

&lt;p&gt;To recap, publish a package to NPM consists of two steps:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Bundle and compile source code to &lt;code&gt;commonjs&lt;/code&gt;, so who install our packge will be able to import it&lt;/li&gt;
&lt;li&gt;Set up a dev script for local development.&lt;/li&gt;
&lt;li&gt;Publish to NPM

&lt;ul&gt;
&lt;li&gt;Control versioning&lt;/li&gt;
&lt;li&gt;Control publishing&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;
  
  
  Bundle and Compile
&lt;/h4&gt;

&lt;p&gt;Tools used: &lt;code&gt;tsup&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;First, go with shell to &lt;code&gt;packages/use-last-visit-date&lt;/code&gt; and&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# install tsup as dev dependency&lt;/span&gt;
pnpm add &lt;span class="nt"&gt;-D&lt;/span&gt; tsup

&lt;span class="c"&gt;# create a src dir&lt;/span&gt;
&lt;span class="nb"&gt;mkdir &lt;/span&gt;src

&lt;span class="c"&gt;# move index.ts to src dir&lt;/span&gt;
&lt;span class="nb"&gt;mv &lt;/span&gt;index.ts src/index.ts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then add a script to &lt;code&gt;packages.json&lt;/code&gt; in &lt;code&gt;packages/use-last-visit-date&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;{
  "scripts": {
&lt;span class="gi"&gt;+   "build": "tsup src/index.ts --format cjs --dts"
&lt;/span&gt;  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This script,will use &lt;code&gt;tsup&lt;/code&gt; to bundle and compile our code, and outputs files to the &lt;code&gt;dist&lt;/code&gt; directory.&lt;br&gt;&lt;br&gt;
Because of that, you should:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;add &lt;code&gt;dist&lt;/code&gt; to your &lt;code&gt;.gitignore&lt;/code&gt; at root of monorepo to avoid push it when &lt;code&gt;git push&lt;/code&gt;ing.&lt;/li&gt;
&lt;li&gt;update &lt;code&gt;package.json&lt;/code&gt; &lt;code&gt;main&lt;/code&gt; property, so who install this packages will use the bundled+compiled version of code.
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;# in packages/use-last-visit-date/package.json
&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="gd"&gt;- "main": "./index.ts",
&lt;/span&gt;&lt;span class="gi"&gt;+ "main": "./dist/index.js",
+ "types": "./dist/index.d.js",
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Because this package is a react package, while developing we need &lt;code&gt;react&lt;/code&gt; and &lt;code&gt;react-dom&lt;/code&gt; installed as dev dependencies.&lt;br&gt;&lt;br&gt;
But we don't want to inject the whole &lt;code&gt;react&lt;/code&gt; code inside our package when it's bundled and compiled.  &lt;/p&gt;

&lt;p&gt;What we want is to let consumer of package install it.&lt;br&gt;&lt;br&gt;
So, add peer dependencies to &lt;code&gt;package.json&lt;/code&gt; in &lt;code&gt;packages/use-last-visit-date&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;&lt;span class="gi"&gt;+  "peerDependencies": {
+      "react": "&amp;gt;=18.2.0",
+      "react-dom": "&amp;gt;=18.2.0"
+  },
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Set up workflow for local development
&lt;/h4&gt;

&lt;p&gt;Before adding &lt;code&gt;tsup&lt;/code&gt;, apps inside &lt;code&gt;apps&lt;/code&gt; directory was importing directly the source code file (with .ts extension).&lt;br&gt;&lt;br&gt;
So, when we updated the source code file, our &lt;code&gt;apps&lt;/code&gt; received the updates.  &lt;/p&gt;

&lt;p&gt;Now we added a compile step in between, so we need to trigger a new &lt;code&gt;build&lt;/code&gt; every time we update source code.  &lt;/p&gt;

&lt;p&gt;To do that, update &lt;code&gt;package.json&lt;/code&gt; in &lt;code&gt;packages/use-last-visit-date&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;{
  "scripts": {
    "build": "tsup src/index.ts --format cjs --dts"
&lt;span class="gi"&gt;+   "dev": "pnpm run build --watch"
&lt;/span&gt;  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;From now on, while developing, we'll use &lt;code&gt;dev&lt;/code&gt; script.  &lt;/p&gt;

&lt;p&gt;Let's test a complete local development workflow.&lt;br&gt;&lt;br&gt;
Go to root of monorepo with shell and run&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pnpm dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will trigger &lt;code&gt;dev&lt;/code&gt; script of every workspace that has a &lt;code&gt;dev&lt;/code&gt; script, in our case:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;packages/use-last-visit-date&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;apps/next&lt;/code&gt;, available at &lt;a href="http://localhost:3000" rel="noopener noreferrer"&gt;http://localhost:3000&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;apps/vite-react&lt;/code&gt;, available at &lt;a href="http://localhost:5173" rel="noopener noreferrer"&gt;http://localhost:5173&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Try to change something in &lt;code&gt;use-last-visit-date&lt;/code&gt; code and watch updates.  &lt;/p&gt;

&lt;h4&gt;
  
  
  Publish to NPM
&lt;/h4&gt;

&lt;p&gt;Every time you update source code, you want that this changes will be published as a new version.&lt;br&gt;&lt;br&gt;
You want also a place where to condense description of changes linked to every new version.  &lt;/p&gt;

&lt;p&gt;You can do it manually, but is very tedious and error prone.&lt;br&gt;
Better to use a tool created for this.&lt;/p&gt;

&lt;p&gt;This is when &lt;code&gt;changeset&lt;/code&gt; enter the pitch.&lt;/p&gt;
&lt;h5&gt;
  
  
  Configure changeset
&lt;/h5&gt;

&lt;p&gt;From root of the monorepo&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# install changeset&lt;/span&gt;
pnpm add &lt;span class="nt"&gt;-w&lt;/span&gt; @changesets/cli

&lt;span class="c"&gt;# setup&lt;/span&gt;
pnpm changeset init
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h5&gt;
  
  
  Create 1.0.0 version
&lt;/h5&gt;

&lt;p&gt;Set &lt;code&gt;version&lt;/code&gt; to &lt;code&gt;0.0.1&lt;/code&gt; in &lt;code&gt;packages/use-last-visit-date/package.json&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"0.0.1"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then use the versionig tool of &lt;code&gt;changeset&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# run this from root monorepo&lt;/span&gt;
pnpm changeset

&lt;span class="c"&gt;# a prompt start&lt;/span&gt;

? Which packages would you like to include?
&lt;span class="c"&gt;# select "use-last-visit-date" with arrows and space&lt;/span&gt;
&lt;span class="c"&gt;# then press enter&lt;/span&gt;

? Which packages should have a major bump?
&lt;span class="c"&gt;# select "use-last-visit-date" with arrows and space&lt;/span&gt;
&lt;span class="c"&gt;# then press enter&lt;/span&gt;

? Are you sure you want to release the first major version of use-last-visit-date?
&lt;span class="c"&gt;# confirm it&lt;/span&gt;

Please enter a summary &lt;span class="k"&gt;for &lt;/span&gt;this change &lt;span class="o"&gt;(&lt;/span&gt;this will be &lt;span class="k"&gt;in &lt;/span&gt;the changelogs&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;
&lt;span class="c"&gt;# write a description&lt;/span&gt;
&lt;span class="c"&gt;# like "First release"&lt;/span&gt;
&lt;span class="c"&gt;# then press enter&lt;/span&gt;

?Is this your desired changeset?
&lt;span class="c"&gt;# confirm it&lt;/span&gt;

&lt;span class="c"&gt;# bump version number&lt;/span&gt;
&lt;span class="c"&gt;# running&lt;/span&gt;
pnpm changeset version
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now &lt;code&gt;version&lt;/code&gt; should be &lt;code&gt;1.0.0&lt;/code&gt;.&lt;/p&gt;

&lt;h5&gt;
  
  
  Publish
&lt;/h5&gt;

&lt;p&gt;Before publish check that every packages in your monorepo that &lt;strong&gt;MUST NOT&lt;/strong&gt; be published has&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"private"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;in its &lt;code&gt;package.json&lt;/code&gt;.&lt;br&gt;&lt;br&gt;
This prevent them to be published to NPM.&lt;/p&gt;

&lt;p&gt;Then update &lt;code&gt;./.changeset/config.json&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;&lt;span class="gd"&gt;- "access": "restricted",
&lt;/span&gt;&lt;span class="gi"&gt;+ "access": "public",
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And....&lt;br&gt;
Finally...&lt;br&gt;
We can publish our package&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pnpm changeset publish
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Done!&lt;/p&gt;

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

&lt;p&gt;I write articles mainly to help future myself or to help the growth of tools I use in my work.&lt;/p&gt;

&lt;p&gt;If this article was helpful to you leave a like.&lt;/p&gt;

&lt;p&gt;Would you like me to talk about a particular topic ?&lt;/p&gt;

&lt;p&gt;Tell me in the comments !&lt;/p&gt;

</description>
      <category>learning</category>
      <category>programming</category>
      <category>development</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Git remove file from not last commit</title>
      <dc:creator>Jacopo Marrone @tresorama</dc:creator>
      <pubDate>Fri, 11 Nov 2022 13:24:52 +0000</pubDate>
      <link>https://dev.to/tresorama/git-remove-file-from-not-last-commit-2nh4</link>
      <guid>https://dev.to/tresorama/git-remove-file-from-not-last-commit-2nh4</guid>
      <description>

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Crossposted on my blog&lt;/strong&gt;&lt;br&gt;
You can read &lt;a href="https://jacopomarrone.com/blog/git-remove-file-from-not-last-commit" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  CAUTION
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Before continue we need to understand that this will break the Git history.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This means that after the fact, in case the commit in question was already pushed you will need to overwrite it with &lt;code&gt;git push --force&lt;/code&gt;, and every repo co-worker will need to &lt;code&gt;git pull --force&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Git and Ethereum, somewhat similar
&lt;/h2&gt;

&lt;p&gt;Git has a chain of commits, called &lt;strong&gt;history&lt;/strong&gt;.&lt;br&gt;
Ethereum/Bitcoin has a chain of blocks, called &lt;strong&gt;blockchain&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Every commit (Git) or block (Ethereum) has a parent commit/block, so when you &lt;strong&gt;&lt;em&gt;edit&lt;/em&gt;&lt;/strong&gt; a block/commit you will change also its children.&lt;/p&gt;

&lt;p&gt;Only what precedes the &lt;strong&gt;&lt;em&gt;changed&lt;/em&gt;&lt;/strong&gt; commit/block remains identical, all that follows will be a new &lt;strong&gt;&lt;em&gt;thing&lt;/em&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;This it's why they say &lt;strong&gt;"Git rebase rewrites history"&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;Note that in practice is not possibile to &lt;strong&gt;&lt;em&gt;edit&lt;/em&gt;&lt;/strong&gt; a commit, you can only overwriting it with a different version of it.&lt;/p&gt;

&lt;p&gt;Git History and blockchain are both immutable.&lt;/p&gt;
&lt;h2&gt;
  
  
  Going back to our problem
&lt;/h2&gt;

&lt;p&gt;My problem is that i've scraped some date on the Web and saved this data on a .json file, this file size is 220MB, and Github let us upload files with a limit of 100MB per file.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;remote: error: File XXX is 220.00 MB; this exceeds GitHub's file size limit of 100 MB&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;But i became aware of that only when i tried to push the repo.&lt;br&gt;
So i need to remove that file from my Git history.&lt;/p&gt;
&lt;h2&gt;
  
  
  Git History
&lt;/h2&gt;

&lt;p&gt;This is the Git History of this example.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;e6cfcb4 &lt;span class="o"&gt;(&lt;/span&gt;HEAD -&amp;gt; main&lt;span class="o"&gt;)&lt;/span&gt; build: update docs about docker adminer &lt;span class="c"&gt;# OK&lt;/span&gt;
d817a6c feat&lt;span class="o"&gt;(&lt;/span&gt;api&lt;span class="o"&gt;)&lt;/span&gt;: get-XXX-by-id now use internal data         &lt;span class="c"&gt;# OK&lt;/span&gt;
9176b01 feat: seed database with scraped data  &lt;span class="c"&gt;# 👈 WRONG ONE&lt;/span&gt;
c1301d1 build: &lt;span class="nb"&gt;install &lt;/span&gt;ts-node &lt;span class="k"&gt;for &lt;/span&gt;running scripts             &lt;span class="c"&gt;# OK&lt;/span&gt;
8c26fd5 feat: add XXX model to db                              &lt;span class="c"&gt;# OK&lt;/span&gt;
e51acdb refactor: folder structure                             &lt;span class="c"&gt;# OK&lt;/span&gt;
e0f1c7f build: add env.example                                 &lt;span class="c"&gt;# OK&lt;/span&gt;
a7d7e34 feat: vote persists &lt;span class="k"&gt;in &lt;/span&gt;db                              &lt;span class="c"&gt;# OK&lt;/span&gt;
f32d6c4 build: imported shadow-database docker instance        &lt;span class="c"&gt;# OK&lt;/span&gt;
987a245 build: implement prisma with first migration           &lt;span class="c"&gt;# OK&lt;/span&gt;
...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We need to :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;keep all commit previous to &lt;code&gt;9176b01&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;edit &lt;code&gt;9176b01&lt;/code&gt; commit , removing the unwanted file&lt;/li&gt;
&lt;li&gt;commit a new version of &lt;code&gt;9176b01&lt;/code&gt; with changes&lt;/li&gt;
&lt;li&gt;recreate all untouched commits after &lt;code&gt;9176b01&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Git rebase interactive
&lt;/h2&gt;

&lt;p&gt;I could be wrong if i say that this is the only way to resolve this problem, I am only a regular developer that stackoverflows when need some help, like all of us 😎.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If you know other solutions or has suggestions write them in the comments !&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Anyway, let's start.&lt;/p&gt;

&lt;h2&gt;
  
  
  Start
&lt;/h2&gt;

&lt;p&gt;As a recap, the &lt;strong&gt;&lt;em&gt;wrong&lt;/em&gt;&lt;/strong&gt; commit is &lt;code&gt;9176b01&lt;/code&gt;,&lt;br&gt;
and last commit before the wrong one is &lt;code&gt;c1301d1&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Start rebasing from last correct commit&lt;/span&gt;
git rebase &lt;span class="nt"&gt;-i&lt;/span&gt; c1301d1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Git will ask instruction on the rebase process.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pick 9176b01 feat: seed database with scarped data
pick d817a6c feat&lt;span class="o"&gt;(&lt;/span&gt;api&lt;span class="o"&gt;)&lt;/span&gt;: get-XXX-by-id now use internal data
pick e6cfcb4 build: update docs about docker adminer

&lt;span class="c"&gt;# Rebase c1301d1..e6cfcb4 onto c1301d1 (3 commands)&lt;/span&gt;
&lt;span class="c"&gt;#&lt;/span&gt;
&lt;span class="c"&gt;# Commands:&lt;/span&gt;
&lt;span class="c"&gt;# p, pick &amp;lt;commit&amp;gt; = use commit&lt;/span&gt;
&lt;span class="c"&gt;# r, reword &amp;lt;commit&amp;gt; = use commit, but edit the commit message&lt;/span&gt;
&lt;span class="c"&gt;# e, edit &amp;lt;commit&amp;gt; = use commit, but stop for amending&lt;/span&gt;
&lt;span class="c"&gt;# s, squash &amp;lt;commit&amp;gt; = use commit, but meld into previous commit&lt;/span&gt;
&lt;span class="c"&gt;# f, fixup [-C | -c] &amp;lt;commit&amp;gt; = like "squash" but keep only the previous&lt;/span&gt;
&lt;span class="c"&gt;#                    commit's log message, unless -C is used, in which case&lt;/span&gt;
&lt;span class="c"&gt;#                    keep only this commit's message; -c is same as -C but&lt;/span&gt;
&lt;span class="c"&gt;#                    opens the editor&lt;/span&gt;
&lt;span class="c"&gt;# x, exec &amp;lt;command&amp;gt; = run command (the rest of the line) using shell&lt;/span&gt;
&lt;span class="c"&gt;# b, break = stop here (continue rebase later with 'git rebase --continue')&lt;/span&gt;
&lt;span class="c"&gt;# d, drop &amp;lt;commit&amp;gt; = remove commit&lt;/span&gt;
&lt;span class="c"&gt;# l, label &amp;lt;label&amp;gt; = label current HEAD with a name&lt;/span&gt;
&lt;span class="c"&gt;# t, reset &amp;lt;label&amp;gt; = reset HEAD to a label&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We must tell Git which commit we want to preserve and which ones we want to edit.&lt;br&gt;
So we tell Git we want to edit &lt;code&gt;9176b01&lt;/code&gt; by swapping &lt;code&gt;pick&lt;/code&gt; with &lt;code&gt;edit&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;edit 9176b01 feat: seed database with scarped data
pick d817a6c feat&lt;span class="o"&gt;(&lt;/span&gt;api&lt;span class="o"&gt;)&lt;/span&gt;: get-XXX-by-id now use internal data
pick e6cfcb4 build: update docs about docker adminer

&lt;span class="c"&gt;# Rebase c1301d1..e6cfcb4 onto c1301d1 (3 commands)&lt;/span&gt;
&lt;span class="c"&gt;#&lt;/span&gt;
&lt;span class="c"&gt;# Commands:&lt;/span&gt;
&lt;span class="c"&gt;# ...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Save with &lt;code&gt;:wq&lt;/code&gt; and Git tell us&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;Stopped at 9176b01...  feat: seed database with scraped data
You can amend the commit now, with

  git commit &lt;span class="nt"&gt;--amend&lt;/span&gt; 

Once you are satisfied with your changes, run

  git rebase &lt;span class="nt"&gt;--continue&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now if we &lt;code&gt;git log --oneline&lt;/code&gt;, we see that our last commit is the wrong one, we are back at that point.&lt;/p&gt;

&lt;p&gt;Let's remove the unwanted file, by&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;rm &lt;/span&gt;path/to/unwanted-file
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Tip:&lt;br&gt;&lt;br&gt;
If you want to keep the file but undo changes made by this &lt;strong&gt;&lt;em&gt;wrong commit&lt;/em&gt;&lt;/strong&gt; use &lt;code&gt;git show path/to/changed-file | git apply -R&lt;/code&gt; instead of &lt;code&gt;rm path/to/file&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;In this example both command produces that same effect because the file didn't exists before this commit, so undo is same as delete.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Add changes to staging area with&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git add path/to/unwanted-file
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git commit &lt;span class="nt"&gt;--amend&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Edit the commit message if you want and confirm with &lt;code&gt;:wq&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Then complete the rebase&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git rebase &lt;span class="nt"&gt;--continue&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Voilà !&lt;br&gt;&lt;br&gt;
Now we have rewritten the Git history from that point.&lt;/p&gt;

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

&lt;p&gt;I write articles mainly to help future myself or to help the growth of tools I use in my work.&lt;/p&gt;

&lt;p&gt;If this article was helpful to you leave a like.&lt;/p&gt;

&lt;p&gt;Would you like me to talk about a particular topic ?&lt;br&gt;&lt;br&gt;
Tell me in the comments !&lt;/p&gt;

</description>
      <category>git</category>
      <category>remove</category>
      <category>commit</category>
      <category>rebase</category>
    </item>
    <item>
      <title>Use tRPC outside React</title>
      <dc:creator>Jacopo Marrone @tresorama</dc:creator>
      <pubDate>Thu, 10 Nov 2022 13:28:43 +0000</pubDate>
      <link>https://dev.to/tresorama/use-trpc-outside-react-d1o</link>
      <guid>https://dev.to/tresorama/use-trpc-outside-react-d1o</guid>
      <description>

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Crossposted on my blog&lt;/strong&gt;&lt;br&gt;
You can read &lt;a href="https://jacopomarrone.com/blog/use-trpc-outside-react"&gt;here&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;blockquote&gt;
&lt;p&gt;“[...] The code easiest to maintain is the code that was never written.”&lt;/p&gt;

&lt;p&gt;-- &lt;cite&gt;Benjamin Franklin&lt;/cite&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If you agree, you should try tRPC.&lt;/p&gt;

&lt;h2&gt;
  
  
  tRPC
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://trpc.io/"&gt;tRPC&lt;/a&gt; is a library that drastically reduce amount of code you need to write to have a fully typed API Layer.&lt;/p&gt;

&lt;p&gt;tRPC can be used with many framework, but a common duo is tRPC and Next.js.&lt;/p&gt;

&lt;p&gt;If you write backend code in Next.js projects and use Typescript, give a try to &lt;strong&gt;tRPC&lt;/strong&gt;, because it &lt;strong&gt;will make you fly&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Typcal tRPC usage pattern with Next.js
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Server side&lt;/strong&gt;, you create a tRPC router and expose it in a Next.js API route.  &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Client side&lt;/strong&gt;, you create a React Hooks that can invoke tRPC router procedures.&lt;br&gt;
Then consume the hook in your React Components, in a React Query similar fashion.&lt;/p&gt;
&lt;h2&gt;
  
  
  But, i need to call tRPC outside React
&lt;/h2&gt;

&lt;p&gt;Many reasons can dictates this:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You want to call the procedure NOT from a React Component&lt;/li&gt;
&lt;li&gt;Your views implement a cache layer (stored in client), so only if cache is empty you submit the HTTP request&lt;/li&gt;
&lt;li&gt;You use Axios and React Query but you are not ready to replace all React Query hooks with tRPC.useQuery, but you want to replace Axios&lt;/li&gt;
&lt;li&gt;You know ...&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In my case i've a cache layer on localStorage and i want only to replace my Axios invocations.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;tRPC vanilla client&lt;/strong&gt; comes into play.&lt;/p&gt;
&lt;h2&gt;
  
  
  tRPC Vanilla Client
&lt;/h2&gt;

&lt;p&gt;Like Axios is a HTTP client, tRPC Vanilla Client is  client used to communicate to tRPC procedures from Vanilla js.&lt;/p&gt;

&lt;p&gt;tRPC Vanilla Client let you call your &lt;code&gt;tRPC procedures&lt;/code&gt; in the same way as &lt;code&gt;trpc.&amp;lt;procedure-name&amp;gt;.useQuery&lt;/code&gt; does.&lt;br&gt;&lt;br&gt;
But unlike &lt;code&gt;trpc.&amp;lt;procedure-name&amp;gt;.useQuery&lt;/code&gt; does, you are not limited to use inside React Components/Hooks.&lt;br&gt;
You can call it whenever you can call a function that returns a Promise.&lt;/p&gt;

&lt;p&gt;Here is how you can replace Axios with it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;
&lt;span class="c1"&gt;// Before&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;axios&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;axios&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;submitFormToServer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;formValues&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;FormValues&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="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="s1"&gt;submittin form to server ...&lt;/span&gt;&lt;span class="dl"&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="c1"&gt;// compose the request DTO&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;dto&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;formValues&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;formValues&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="c1"&gt;// submit HTTP request to API Layer&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;axios&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&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/post&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;dto&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// parse request result&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="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="s1"&gt;success&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="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;success&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// falltrough catch&lt;/span&gt;

  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;error:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;success&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Page&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleSubmit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;formValues&lt;/span&gt; &lt;span class="o"&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;success&lt;/span&gt;&lt;span class="p"&gt;}&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;submitFormToServer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;formValues&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;form&lt;/span&gt; &lt;span class="na"&gt;onSubmit&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;handleSubmit&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;...&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;form&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; 
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;
&lt;span class="c1"&gt;// After&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;trpcVanilla&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;../utils/trpc&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;submitFormToServer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;formValues&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;FormValues&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="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="s1"&gt;submittin form to server ...&lt;/span&gt;&lt;span class="dl"&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="c1"&gt;// submit HTTP request to tRPC API Layer&lt;/span&gt;
     &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;trpcVanilla&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createPost&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mutate&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;formValues&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;formValues&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;success&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;success&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;




&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Page&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleSubmit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;formValues&lt;/span&gt; &lt;span class="o"&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;success&lt;/span&gt;&lt;span class="p"&gt;}&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;submitFormToServer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;formValues&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;form&lt;/span&gt; &lt;span class="na"&gt;onSubmit&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;handleSubmit&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;...&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;form&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; 
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  How to create tRPC Vanilla Client
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://trpc.io/docs/v10/vanilla"&gt;View Documentation&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Example&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// in /utils/trpc.ts&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;createTRPCProxyClient&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;httpBatchLink&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;@trpc/client&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="kd"&gt;type&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;AppRouter&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;...path to your tRPC router&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;trpcVanilla&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;createTRPCProxyClient&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;AppRouter&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;links&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="nf"&gt;httpBatchLink&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`http://localhost:3000/api/trpc`&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;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;I write articles mainly to help future myself or to help the growth of tools I use in my work.&lt;/p&gt;

&lt;p&gt;If this article was helpful to you leave a like.&lt;/p&gt;

&lt;p&gt;Would you like me to talk about a particular topic ?&lt;br&gt;&lt;br&gt;
Tell me in the comments !&lt;/p&gt;

</description>
      <category>trpc</category>
      <category>react</category>
      <category>fetch</category>
      <category>reactquery</category>
    </item>
    <item>
      <title>React - Don't update parent state in the rendering phase of the child</title>
      <dc:creator>Jacopo Marrone @tresorama</dc:creator>
      <pubDate>Wed, 19 Jan 2022 17:14:00 +0000</pubDate>
      <link>https://dev.to/tresorama/react-dont-update-parent-state-in-the-rendering-phase-of-the-child-h7c</link>
      <guid>https://dev.to/tresorama/react-dont-update-parent-state-in-the-rendering-phase-of-the-child-h7c</guid>
      <description>&lt;p&gt;TLDR;&lt;br&gt;
&lt;strong&gt;Don't update parent state in the rendering phase of the child component&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Long story
&lt;/h2&gt;

&lt;p&gt;Visualize in your mind this Abstract React tree:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;WebSite&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;

  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;LoadingSpinner&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;

  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;PageContent&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;A&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ASub&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ASubSub&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;LoadingTriggerA&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;ASubSub&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;ASub&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;A&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;B&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;BSub&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;BSubSub&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;LoadingTriggerB&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;BSubSub&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;BSub&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;B&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;PageContent&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;WebSite&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;The goal is to render a single LoadingSpinner in our whole website, and being able to trigger the LoadingSpinner visibility from &lt;code&gt;LoadingTriggerA&lt;/code&gt; and &lt;code&gt;LoadingTriggerB&lt;/code&gt; when they need to.&lt;/p&gt;

&lt;p&gt;How to solve this without passing functions down the tree - aka “prop drilling“ ?&lt;/p&gt;

&lt;p&gt;React Context, using a "useAppLoading" custom hook.&lt;/p&gt;

&lt;p&gt;This custom hook takes care of maintaining the visibility state of the Loading component, and to render it.&lt;br&gt;
This hook exposes us a &lt;code&gt;show&lt;/code&gt; and a &lt;code&gt;hide&lt;/code&gt; function.&lt;/p&gt;

&lt;p&gt;In this post we are focused not on the custom hook, but here you can find the code for build a &lt;a href="https://magz.techover.io/2020/03/01/loading-indicator-with-react-context-api-hooks/"&gt;"useAppLoading" custom hook&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;AppLoadingProvider&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useAppLoading&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;./my-custom-hook/useAppLoading&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Website&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="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;AppLoadingProvider&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;PageContent&lt;/span&gt;  &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt; // LoadingTriggerA and LoadingTriggerB are descendants of this
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;AppLoadingProvider&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;LoadingTriggerA&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="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;showLoading&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;hideLoading&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useAppLoading&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
   &lt;span class="p"&gt;...&lt;/span&gt;
   &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;....&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;LoadingTriggerB&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="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;showLoading&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;hideLoading&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useAppLoading&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
   &lt;span class="p"&gt;...&lt;/span&gt;
   &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;....&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It seams ok.&lt;br&gt;
But how do we call "show()" and "hide()" functions ???&lt;br&gt;
This is &lt;strong&gt;THE POINT&lt;/strong&gt; of this post.&lt;/p&gt;

&lt;p&gt;Maybe like this ??&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;LoadingTriggerA&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="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;showLoading&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;hideLoading&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useAppLoading&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
   &lt;span class="nf"&gt;showLoading&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
   &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;....&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;LoadingTriggerB&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="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;showLoading&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;hideLoading&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useAppLoading&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
   &lt;span class="nf"&gt;hideLoading&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
   &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;....&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Try yourself and you will notice that React javascript console triggers an error in the console saying:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Warning:
Cannot update a component (`AppLoadingProvider`) while rendering a different component (`LoadingTriggerA`).
To locate the bad setState() call inside `LoadingTriggerA`,
follow the stack trace as described in https://reactjs.org/link/setstate-in-render
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What this means is that, child component can't update one of his parents component's state from within the rendering body.&lt;br&gt;
That's what this warning is telling you.&lt;/p&gt;

&lt;p&gt;This is an Anti Pattern because if it was legal, there will be chances that data flow going crazy, and weird stuff will happen, like unnecessary re rendering  of the tree.&lt;/p&gt;

&lt;p&gt;In our case the Parent is the AppLoadingProvider, which treat LoadingTriggerA and LoadingTriggerB as descendants.&lt;/p&gt;

&lt;p&gt;So How to solve that ??&lt;/p&gt;

&lt;p&gt;Update the (parent) state inside an useEffect, because useEffect runs after the main rendering phase of a component.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;LoadingTriggerA&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="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;busy&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setBusy&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&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;showLoading&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;hideLoading&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useAppLoading&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

   &lt;span class="nx"&gt;React&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="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;busy&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nf"&gt;showLoading&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
     &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="nf"&gt;hideLoading&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;busy&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

   &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;....&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Thank you for reading this blog post.&lt;br&gt;
Not clear ? Question ? Ask in comments !!&lt;/p&gt;

</description>
      <category>react</category>
      <category>hook</category>
      <category>state</category>
      <category>effect</category>
    </item>
  </channel>
</rss>
