<?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: Hleb Kryshyn</title>
    <description>The latest articles on DEV Community by Hleb Kryshyn (@dealwith).</description>
    <link>https://dev.to/dealwith</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%2F612527%2F47052a88-d312-42a3-a9cd-21542bd6d08c.JPG</url>
      <title>DEV Community: Hleb Kryshyn</title>
      <link>https://dev.to/dealwith</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/dealwith"/>
    <language>en</language>
    <item>
      <title>Everything you have to know about React 19 ⚛️</title>
      <dc:creator>Hleb Kryshyn</dc:creator>
      <pubDate>Sat, 29 Jun 2024 17:57:59 +0000</pubDate>
      <link>https://dev.to/dealwith/everything-you-have-to-know-about-react-19-3bgf</link>
      <guid>https://dev.to/dealwith/everything-you-have-to-know-about-react-19-3bgf</guid>
      <description>&lt;p&gt;🤓 I want to equip you with the needed knowledge for before the new update will hit your production.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this updated was created?
&lt;/h2&gt;

&lt;p&gt;The idea of the udpate is to make the UI more &lt;em&gt;Optimistic&lt;/em&gt; less struggle, less code, and less external libraries.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Optimistic UI?
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;The Optimistic UI&lt;/em&gt; is the way to show user a change in the UI before the response from the server reaches the client.&lt;/p&gt;

&lt;h2&gt;
  
  
  5 features that will help you implement a better UI with React 19
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. useOptimistic
&lt;/h3&gt;

&lt;p&gt;New hook &lt;code&gt;useOptimistic&lt;/code&gt; will help us to calculate the optimistic value within a single hook.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useOptimistic&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;function&lt;/span&gt; &lt;span class="nf"&gt;AppContainer&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setState&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;optimisticState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;addOptimistic&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useOptimistic&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="c1"&gt;// updateFn&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;currentState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;optimisticValue&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="err"&gt;→&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="c1"&gt;// merge and return new state&lt;/span&gt;
   &lt;span class="c1"&gt;// with optimistic value   &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;h3&gt;
  
  
  2. useTransition
&lt;/h3&gt;

&lt;p&gt;hook &lt;code&gt;useTransition&lt;/code&gt; which was added previously, right now the &lt;code&gt;async&lt;/code&gt; transitions are supported&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;function&lt;/span&gt; &lt;span class="nf"&gt;UpdateName&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setName&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="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setError&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="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;isPending&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;startTransition&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useTransition&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleSubmit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;startTransition&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="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;error&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;updateName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&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;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="nf"&gt;setError&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="p"&gt;}&lt;/span&gt;
            &lt;span class="nf"&gt;redirect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/path&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="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;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;name&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;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt; 
            &lt;span class="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;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;handleSubmit&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;disabled&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;isPending&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;Update&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;            &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&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="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/p&amp;gt;&lt;/span&gt;&lt;span class="err"&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;&lt;code&gt;useTransition&lt;/code&gt; is helping us to update state without blocking the UI and providing the &lt;code&gt;pending&lt;/code&gt; state by default.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. New API &lt;code&gt;use&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;New function &lt;code&gt;use&lt;/code&gt; will help us to resolve async actions.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;use&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;function&lt;/span&gt; &lt;span class="nf"&gt;Comments&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="nx"&gt;commentsPromise&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// `use` will suspend until the promise resolves.&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;comments&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;commentsPromise&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;comments&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;comment&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;p&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;comment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;comment&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&amp;gt;&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="err"&gt;;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can also resolve the &lt;code&gt;Context&lt;/code&gt; with the &lt;code&gt;use&lt;/code&gt; function&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;use&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;ThemeContext&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;./ThemeContext&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Heading&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;theme&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ThemeContext&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;h1&lt;/span&gt; &lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt;&lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;theme&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;color&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;children&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="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  4. Ref as a prop
&lt;/h3&gt;

&lt;p&gt;Best feature of the new update 🚀&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function MyInput({placeholder, ref}) {
  return &amp;lt;input placeholder={placeholder} ref={ref} /&amp;gt;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No need for the &lt;code&gt;forwardRef&lt;/code&gt; since &lt;code&gt;React 19&lt;/code&gt; 👏&lt;/p&gt;

&lt;h3&gt;
  
  
  5. React Compiler
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;React Compiler&lt;/code&gt; is a tool to automatically optimize your code at a build time.&lt;/p&gt;

&lt;h4&gt;
  
  
  What we expect from the compiler?
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;Skipping cascading re-rendering of components
Re-rendering &lt;code&gt;&amp;lt;Parent /&amp;gt;&lt;/code&gt; causes many components in its component tree to re-render, even though only &lt;code&gt;&amp;lt;Parent /&amp;gt;&lt;/code&gt; has changed.&lt;/li&gt;
&lt;li&gt;Skipping expensive calculations from outside of &lt;code&gt;React&lt;/code&gt;
For example, calling &lt;code&gt;expensivelyProcessAReallyLargeArrayOfObjects()&lt;/code&gt; inside of your component or hook that needs that data&lt;/li&gt;
&lt;li&gt;Memoizing deps to effects
To ensure that a dependency of a hook is still &lt;code&gt;===&lt;/code&gt; on re-rendering so as to prevent an infinite loop in a hook such as &lt;code&gt;useEffect()&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  🤰 When do we expect Compiler?
&lt;/h4&gt;

&lt;p&gt;My assumption is late 2024, the info I got from the Andrew's Clark &lt;a href="https://x.com/acdlite/status/1758229889595977824" rel="noopener noreferrer"&gt;post on X&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  🏁 Finish
&lt;/h2&gt;

&lt;p&gt;Share in comments your thoughts regarding how &lt;code&gt;React&lt;/code&gt; codebase will be similar to any other JS framework after the &lt;code&gt;Compiler&lt;/code&gt; being integrated in the codebases 😁&lt;/p&gt;

&lt;p&gt;Have a good React 19 🚀&lt;/p&gt;

</description>
      <category>react19</category>
      <category>react</category>
      <category>javascript</category>
      <category>compiler</category>
    </item>
    <item>
      <title>How to implement Typescript Function overload</title>
      <dc:creator>Hleb Kryshyn</dc:creator>
      <pubDate>Mon, 16 Oct 2023 15:00:00 +0000</pubDate>
      <link>https://dev.to/dealwith/how-to-implement-typescript-function-overload-1ogb</link>
      <guid>https://dev.to/dealwith/how-to-implement-typescript-function-overload-1ogb</guid>
      <description>&lt;p&gt;👋 Hey folks! In this post, I want to cover the topic of function overloading and explain why it's essential to understand this concept, and why you shouldn't be afraid to use it!&lt;/p&gt;

&lt;h2&gt;
  
  
  📃 Wiki Definition
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;Function overloading or method overloading is the ability to create multiple functions of the same name with different implementations. Calls to an overloaded function will run a specific version of that function appropriate to the context of the call.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  🧐 Wiki Definition Explanation
&lt;/h2&gt;

&lt;p&gt;In short &lt;em&gt;function overloading&lt;/em&gt; is a function with multiple call signatures. This means there are multiple ways to call a function.&lt;/p&gt;

&lt;p&gt;Example:&lt;br&gt;
Let's take a look at the example of a function which might be called in a few ways with different arguments&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="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;ProductParams&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;promo&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt;
    &lt;span class="nx"&gt;isArchived&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getProducts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ProductParams&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;url&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;URL&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/v1/products&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;urlParams&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;URLSearchParams&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;promo&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;urlParams&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;promo&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;promo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;isArchived&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;urlParams&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;isArchived&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isArchived&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;search&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;urlParams&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toString&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="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can call this &lt;code&gt;function&lt;/code&gt; in 2 different ways, with 2 different params. Our function will return from the &lt;code&gt;API&lt;/code&gt; products that might be &lt;code&gt;promo&lt;/code&gt; or &lt;code&gt;archived&lt;/code&gt;, or both &lt;code&gt;promo&lt;/code&gt; and &lt;code&gt;archived&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  🔍 Multiple Function Signatures
&lt;/h2&gt;

&lt;p&gt;Typescript's approach to function overloading is quite distinct from some other languages. Instead of having multiple function definitions, TypeScript uses multiple function signatures followed by a single function body.&lt;/p&gt;

&lt;p&gt;The type-checker evaluates these signatures from top to bottom. This order matters because TypeScript will use the first signature that matches the function call. For instance, if a function call can match two overloaded signatures, TypeScript will choose the one that's listed first. Therefore, it's advisable to list more specific signatures higher and keep broader ones below.&lt;/p&gt;

&lt;h2&gt;
  
  
  💻 Let's implement the overloading for the example function
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Product Interfaces&lt;/span&gt;
&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;PromoProducts&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;//... some properties specific to promo products&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;ArchivedProducts&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;//... some properties specific to archived products&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;PromoAndArchivedProducts&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;//... some properties combining both promo and archived products&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;ProductParams&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;promo&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt;
    &lt;span class="nx"&gt;isArchived&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="c1"&gt;// Function overloading signatures&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getProducts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;promo&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="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;PromoProducts&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;function&lt;/span&gt; &lt;span class="nf"&gt;getProducts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;isArchived&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="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ArchivedProducts&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;function&lt;/span&gt; &lt;span class="nf"&gt;getProducts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;promo&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="nx"&gt;isArchived&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="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;PromoAndArchivedProducts&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;function&lt;/span&gt; &lt;span class="nf"&gt;getProducts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ProductParams&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;url&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;URL&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/v1/products&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;urlParams&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;URLSearchParams&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;promo&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;urlParams&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;promo&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;maxPrice&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;isArchived&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;urlParams&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;isArchived&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isArchived&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;search&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;urlParams&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toString&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="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&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;After the implementation, we will be able to use our &lt;code&gt;function&lt;/code&gt; in different ways and have a type of safety in place.&lt;/p&gt;

&lt;h2&gt;
  
  
  🏁 Finish
&lt;/h2&gt;

&lt;p&gt;I recommend not being afraid to use function overloading. It's so helpful when you're providing type-rich interfaces and aiming for better code readability and safety.&lt;/p&gt;

</description>
      <category>typescript</category>
      <category>frontend</category>
    </item>
    <item>
      <title>Singleton pattern in react application</title>
      <dc:creator>Hleb Kryshyn</dc:creator>
      <pubDate>Thu, 15 Jun 2023 22:39:27 +0000</pubDate>
      <link>https://dev.to/dealwith/singleton-pattern-in-react-application-1ijj</link>
      <guid>https://dev.to/dealwith/singleton-pattern-in-react-application-1ijj</guid>
      <description>&lt;h2&gt;
  
  
  💭 Intro
&lt;/h2&gt;

&lt;p&gt;In this article, I want to share my experience using the singleton pattern as a service inside a production React application.&lt;/p&gt;

&lt;h2&gt;
  
  
  🌧️ Problem
&lt;/h2&gt;

&lt;p&gt;We had many places to handle the localisation logic. Our application is a multi-language web app that supports three languages. This results in constant interaction with localisation. However, the issue is that functions are spread across the application for all utilities connected to localisation. Sometimes, even one function was using a set of two languages and the other three languages. Such a mess was creating bugs and misunderstandings.&lt;/p&gt;

&lt;h2&gt;
  
  
  ⚡️ Pattern solution
&lt;/h2&gt;

&lt;p&gt;Such a task can be solved by implementing a singleton pattern because it's shared across the whole application and provides strict access control. It helped our team to centralize the localisation helpers in one place, and it also helps us to reduce the risk of bugs and misunderstanding by providing clear documentation for the methods and usage of the service.&lt;/p&gt;

&lt;h2&gt;
  
  
  🤔 What is the Singleton pattern?
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;"Singleton is a creational design pattern that lets you ensure that a class has only one instance while providing a global access point to this instance."&lt;/em&gt; - &lt;a href="https://refactoring.guru/design-patterns/singleton#intent" rel="noopener noreferrer"&gt;Refactoring Guru&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  💡 According to the statement it's exactly what we need!
&lt;/h2&gt;

&lt;p&gt;First, we should have only one instance throughout the whole application, which should be the source of truth.&lt;/p&gt;

&lt;p&gt;Second, the instance should be accessed globally and be protected from overwriting from another part of the application because the whole application should use the same number of languages.&lt;/p&gt;

&lt;h2&gt;
  
  
  💻 Implementation
&lt;/h2&gt;

&lt;p&gt;1) &lt;strong&gt;Singleton Class Definition&lt;/strong&gt;&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;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;LocalisationService&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="nx"&gt;instance&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;LocalisationService&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is the basic structure of our Singleton class, LocalisationService. We declare a private static variable instance of the same class. This variable will hold the single instance of our class.&lt;/p&gt;

&lt;p&gt;2) &lt;strong&gt;Private Constructor and Static Creation Method&lt;/strong&gt;&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;private&lt;/span&gt; &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;languages&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;LanguageCode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;EN&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;shortName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;LanguageCode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;EN&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;longName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;LanguageName&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ENGLISH&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;LanguageCode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;DE&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;shortName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;LanguageCode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;DE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;longName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;LanguageName&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;DEUTSCH&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;LanguageCode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;FR&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;shortName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;LanguageCode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;FR&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;longName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;LanguageName&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;FRANCAIS&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;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="nf"&gt;getInstance&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nx"&gt;LocalizationService&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;LocalizationService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;instance&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;LocalizationService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;instance&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;LocalizationService&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;LocalizationService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;instance&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, we have a private constructor that initializes the languages object. The constructor is private to prevent creating new instances of the class from outside. The getInstance method is a public static method that returns the single instance of the LocalizationService class. If the instance does not exist, it creates a new one.&lt;/p&gt;

&lt;p&gt;3) &lt;strong&gt;Public Methods&lt;/strong&gt;&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;export&lt;/span&gt; &lt;span class="kr"&gt;enum&lt;/span&gt; &lt;span class="nx"&gt;LanguageCode&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;EN&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;en&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;DE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;de&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;FR&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;fr&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;export&lt;/span&gt; &lt;span class="kr"&gt;enum&lt;/span&gt; &lt;span class="nx"&gt;LanguageName&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;ENGLISH&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;English&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;DEUTSCH&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Deutsch&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;FRANCAIS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Français&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;export&lt;/span&gt; &lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;Language&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;shortName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;LanguageCode&lt;/span&gt;
  &lt;span class="nx"&gt;longName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;LanguageName&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These are the public methods of our Singleton class. getAllLanguages returns all available languages. getLanguageByShortName returns a specific language by its short name. getLanguagesExcept returns all languages except the one specified by the key.&lt;/p&gt;

&lt;p&gt;4) Using the Singleton Service&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;LanguageCode&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;LocalizationService&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;services&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;localizationService&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;LocalizationService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getInstance&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is how we use our Singleton service in our code. We import the LocalizationService and call the getInstance method to get the single instance of the service.&lt;/p&gt;

&lt;h3&gt;
  
  
  The code of the whole Service
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kr"&gt;enum&lt;/span&gt; &lt;span class="nx"&gt;LanguageCode&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;EN&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;en&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;DE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;de&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;FR&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;fr&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;export&lt;/span&gt; &lt;span class="kr"&gt;enum&lt;/span&gt; &lt;span class="nx"&gt;LanguageName&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;ENGLISH&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;English&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;DEUTSCH&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Deutsch&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;FRANCAIS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Français&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;export&lt;/span&gt; &lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;Language&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;shortName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;LanguageCode&lt;/span&gt;
  &lt;span class="nx"&gt;longName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;LanguageName&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="cm"&gt;/**
 * Represents the localization service, responsible for managing language-related tasks.
 * This class follows the Singleton pattern to ensure only one instance is used throughout the application.
 */&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;LocalizationService&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="nx"&gt;instance&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;LocalizationService&lt;/span&gt;
  &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;languages&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;key&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="nx"&gt;Language&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="cm"&gt;/**
   * Initializes a new instance of the LocalizationService class.
   * The constructor is private to prevent instantiation from outside the class.
   */&lt;/span&gt;
  &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;languages&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;LanguageCode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;EN&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;shortName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;LanguageCode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;EN&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;longName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;LanguageName&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ENGLISH&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;LanguageCode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;DE&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;shortName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;LanguageCode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;DE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;longName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;LanguageName&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;DEUTSCH&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;LanguageCode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;FR&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;shortName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;LanguageCode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;FR&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;longName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;LanguageName&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;FRANCAIS&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="cm"&gt;/**
   * Retrieves the single instance of the LocalizationService class.
   * If an instance does not exist, it creates a new one.
   * @returns {LocalizationService} The single instance of the LocalizationService class.
   */&lt;/span&gt;
  &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="nf"&gt;getInstance&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nx"&gt;LocalizationService&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;LocalizationService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;instance&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;LocalizationService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;instance&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;LocalizationService&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;LocalizationService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;instance&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="cm"&gt;/**
   * Retrieves an array of all available languages.
   * @returns {Language[]} An array containing all available languages.
   */&lt;/span&gt;
  &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;getAllLanguages&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nx"&gt;Language&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="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;values&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;languages&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="cm"&gt;/**
   * Retrieves a language by its short name.
   * @param {LanguageCode} shortName - The short name of the language to retrieve.
   * @returns {Language | undefined} The language with the specified short name, or undefined if not found.
   */&lt;/span&gt;
  &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;getLanguageByShortName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;shortName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;LanguageCode&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;Language&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;languages&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;shortName&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="cm"&gt;/**
   * Retrieves an array of all languages except the one specified by the key.
   * @param {LanguageCode} key - The key of the language to exclude from the result.
   * @returns {Language[]} An array containing all languages except the one specified by the key.
   */&lt;/span&gt;
  &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;getLanguagesExcept&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;LanguageCode&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;Language&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getAllLanguages&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;language&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;language&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;shortName&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="nx"&gt;key&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;
  
  
  🏁 Result
&lt;/h2&gt;

&lt;p&gt;I have a good feeling about how this pattern fits into the React application development ecosystem. We already saw its success of it through popular libraries such as Redux. Implementing this pattern in a production application brought us development benefits in terms of consistency and development speed.&lt;/p&gt;

&lt;p&gt;If you have any questions regarding this or other patterns, let's discuss them in the comments!&lt;/p&gt;

&lt;p&gt;🧐 Do you have any other examples of design pattern implementation in your React codebase? Share it!&lt;/p&gt;

</description>
      <category>react</category>
      <category>singleton</category>
      <category>designpatterns</category>
    </item>
    <item>
      <title>Chat GPT 🆚 Notion AI (Blog post)</title>
      <dc:creator>Hleb Kryshyn</dc:creator>
      <pubDate>Sun, 02 Apr 2023 15:20:02 +0000</pubDate>
      <link>https://dev.to/dealwith/chat-gpt-notion-ai-blog-post-8km</link>
      <guid>https://dev.to/dealwith/chat-gpt-notion-ai-blog-post-8km</guid>
      <description>&lt;p&gt;Let's check how ChatGPT and Notion AI will deal with the task of writing a "Blog Post about the advantages of AI usage".&lt;/p&gt;

&lt;p&gt;That should be a pretty easy task for the AI because it doesn't require powerful historical plugins or programming skills, and the AI should be able to write about its own advantage 😉&lt;/p&gt;

&lt;h2&gt;
  
  
  Overview 🔭
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Notion AI article - The Advantages of AI Usage&lt;/li&gt;
&lt;li&gt;ChatGPT article - Embracing the Future: The Advantages of AI Usage&lt;/li&gt;
&lt;li&gt;Summary&lt;/li&gt;
&lt;li&gt;Comparison table&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can read this articles here or in Notion, because there I can split the articles in two column so it will be easier for you to read and compare face to face:&lt;br&gt;
&lt;a href="https://www.notion.so/Blog-Post-about-the-advantages-of-AI-usage-ChatGPT-vs-Notion-AI-c15e8eb65f81462f9a29ed69dfdab7e2?pvs=4" rel="noopener noreferrer"&gt;https://www.notion.so/Blog-Post-about-the-advantages-of-AI-usage-ChatGPT-vs-Notion-AI-c15e8eb65f81462f9a29ed69dfdab7e2?pvs=4&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Notion AI article
&lt;/h2&gt;

&lt;h3&gt;
  
  
  The Advantages of AI Usage
&lt;/h3&gt;

&lt;p&gt;Artificial Intelligence (AI) has revolutionized the world we live in. From personal assistants to self-driving cars, AI has made our lives easier and more convenient. The advantages of AI usage are numerous and far-reaching, and in this article, we will discuss some of the key benefits.&lt;/p&gt;

&lt;h4&gt;
  
  
  Increased Efficiency (Notion AI)
&lt;/h4&gt;

&lt;p&gt;One of the most significant advantages of AI is that it can perform tasks at a much faster pace than humans. AI systems can process vast amounts of data in a matter of seconds, which is impossible for humans to do. This speed leads to increased efficiency in various sectors, such as healthcare, finance, and logistics. AI-powered machines and robots can work around the clock with little or no breaks, which significantly increases work output and production.&lt;/p&gt;

&lt;h4&gt;
  
  
  Improved Accuracy (Notion AI)
&lt;/h4&gt;

&lt;p&gt;AI systems are highly accurate, and they can perform repetitive tasks without getting tired or making mistakes. This accuracy is critical in fields such as finance and healthcare, where a small error can have severe consequences. AI systems can also analyze vast amounts of data to identify patterns and trends that humans may not be able to detect. In the healthcare industry, AI-powered machines can detect diseases and symptoms that humans may miss, leading to more accurate diagnoses and better treatment options.&lt;/p&gt;

&lt;h4&gt;
  
  
  Cost Savings (Notion AI)
&lt;/h4&gt;

&lt;p&gt;Implementing AI systems can lead to significant cost savings for businesses. AI can automate many tasks that would otherwise require human labor, such as data entry, customer service, and quality control. This automation can reduce labor costs, increase productivity, and improve the bottom line. AI-powered machines can also operate more efficiently than humans, which reduces energy consumption and maintenance costs.&lt;/p&gt;

&lt;h4&gt;
  
  
  Personalization (Notion AI)
&lt;/h4&gt;

&lt;p&gt;AI can be used to personalize the user experience in various industries, such as e-commerce and marketing. By analyzing customer data, AI can recommend products and services that are tailored to each customer's needs and preferences. This personalization can lead to increased customer satisfaction and loyalty. With the help of AI-powered chatbots, businesses can provide personalized customer service and support to their clients, leading to more sales and customer retention.&lt;/p&gt;

&lt;h4&gt;
  
  
  Predictive Maintenance (Notion AI)
&lt;/h4&gt;

&lt;p&gt;AI can also be used to monitor and maintain machinery and equipment. By analyzing data from sensors and other sources, AI systems can predict when equipment will need maintenance or repairs. This proactive approach can reduce downtime and maintenance costs and improve overall efficiency. AI-powered machines can also detect and diagnose problems before they occur, leading to fewer breakdowns and longer equipment lifespan.&lt;/p&gt;

&lt;h4&gt;
  
  
  Improved Decision Making by Notion AI
&lt;/h4&gt;

&lt;p&gt;AI can help decision-makers make better decisions by providing them with accurate and relevant information. AI systems can analyze vast amounts of data and provide insights and recommendations that humans may not be able to identify. This information can help businesses make more informed decisions and improve their overall performance. In the finance industry, AI-powered algorithms can analyze market trends and make investment decisions based on the data collected, leading to more significant returns on investments.&lt;/p&gt;

&lt;p&gt;In conclusion, the advantages of AI usage are many, and its potential for future growth is enormous. As AI technology continues to advance, we can expect to see even more benefits in various sectors. However, it is essential to consider the ethical and social implications of AI, such as privacy concerns and job displacement, and work to address these issues. With proper regulations and guidelines, AI can become a powerful tool that enhances our lives and transforms the way we work and interact with the world around us.&lt;/p&gt;

&lt;h2&gt;
  
  
  ChatGPT article
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Embracing the Future: The Advantages of AI Usage
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Introduction by ChatGPT
&lt;/h4&gt;

&lt;p&gt;Artificial intelligence (AI) has become a vital part of our daily lives. From smartphones to medical diagnostics, AI has revolutionized the way we interact with technology and the world around us. As AI continues to advance and becomes more integrated into our society, we must consider the various advantages it brings. In this blog post, we will delve into the numerous benefits of AI usage, including increased efficiency, improved decision-making, and enhanced personalization.&lt;/p&gt;

&lt;h4&gt;
  
  
  Increased Efficiency by ChatGPT
&lt;/h4&gt;

&lt;p&gt;One of the most significant advantages of AI usage is the increased efficiency it offers in various sectors. AI-powered systems can process and analyze vast amounts of data at incredible speeds, far surpassing human capabilities. This enhanced processing power allows businesses and organizations to streamline operations, reduce costs, and increase productivity.&lt;/p&gt;

&lt;p&gt;For example, AI algorithms can optimize supply chain management, ensuring that products are delivered on time and with minimal waste. Additionally, AI-powered chatbots can handle customer inquiries, freeing up human workers to focus on more complex tasks. This improved efficiency benefits both businesses and consumers, leading to increased innovation and economic growth.&lt;/p&gt;

&lt;h4&gt;
  
  
  Improved Decision-Making (ChatGPT)
&lt;/h4&gt;

&lt;p&gt;AI systems can analyze vast amounts of data and identify patterns that would otherwise go unnoticed by human analysts. This ability allows AI to support improved decision-making in various fields, such as finance, healthcare, and even politics.&lt;/p&gt;

&lt;p&gt;In finance, AI algorithms can identify trends and make predictions that help investors make informed decisions. In healthcare, AI-powered diagnostic tools can analyze medical images and patient data, assisting doctors in making accurate diagnoses and recommending personalized treatment plans. By enhancing our ability to make informed decisions, AI can lead to better outcomes and improved quality of life.&lt;/p&gt;

&lt;h4&gt;
  
  
  Enhanced Personalization (ChatGPT)
&lt;/h4&gt;

&lt;p&gt;AI has the potential to revolutionize the way we experience personalized products and services. By analyzing user preferences and behavior, AI-powered systems can create tailor-made experiences that cater to individual needs and desires.&lt;/p&gt;

&lt;p&gt;For instance, AI-driven recommendation engines can suggest products, content, or experiences that align with a user's interests, making it easier for consumers to discover new products and services. In education, AI can create personalized learning plans that adapt to a student's unique learning style, leading to improved academic performance and engagement.&lt;/p&gt;

&lt;h4&gt;
  
  
  Advancements in Research and Innovation (ChatGPT)
&lt;/h4&gt;

&lt;p&gt;AI has the potential to accelerate scientific research and innovation by automating time-consuming tasks and processing large datasets. In the field of drug discovery, AI algorithms can quickly analyze millions of chemical compounds, helping researchers identify promising candidates for new medications. Additionally, AI can aid in the development of new materials, energy solutions, and environmental conservation strategies, contributing to a more sustainable and prosperous future.&lt;/p&gt;

&lt;h4&gt;
  
  
  Democratization of Technology (ChatGPT)
&lt;/h4&gt;

&lt;p&gt;As AI becomes more accessible and affordable, it has the potential to democratize technology, making advanced tools and services available to a broader range of people. Small businesses and individuals can leverage AI-powered solutions to compete with larger corporations, fostering innovation and promoting economic growth. Additionally, AI can help bridge the digital divide by making essential services, such as healthcare and education, more accessible to underserved communities.&lt;/p&gt;

&lt;h4&gt;
  
  
  Conclusion by ChatGPT
&lt;/h4&gt;

&lt;p&gt;The advantages of AI usage are vast and far-reaching, potentially tran various aspects of our lives. By harnessing the power of AI, we can unlock increased efficiency, improved decision-making, enhanced personalization, advancements in research and innovation, and the democratization of technology. As we continue to develop and refine AI technologies, it is crucial to consider the ethical implications and strive for responsible implementation to ensure that the benefits of AI are felt by all.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Notion AI&lt;/strong&gt; split the article into six parts. Every part explains well what we need - "advantages."&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Notion AI&lt;/strong&gt; touch on several topics:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;How &lt;em&gt;AI can increase speed in various&lt;/em&gt; fields of our day-to-day life. I would agree, but speed doesn't mean quality😉. Here I agree with Marques Brownlee in the video &lt;a href="https://www.youtube.com/watch?v=7emz4zZ226E" rel="noopener noreferrer"&gt;"The Biggest Problem with AI"&lt;/a&gt;, the AI is giving convincing answers until you are not a professional in the topic, and when you're are a professional you're starting to see the mistakes. From my experience, in most of the problems I faced with debugging, the AI didn't help much there.&lt;/li&gt;
&lt;li&gt;The decision-making improvement. I agree in some way. On the other side, I see a lot of guys in the coffee who are trying to solve every problem with AI without and not trying to gain expertise in any topic. So here, I agree 50/50 that this is an advantage. Because, again, AI cannot check the facts right now.&lt;/li&gt;
&lt;li&gt;
Cost savings and Personalization part is an absolutely true thing.&lt;/li&gt;
&lt;li&gt;
Predictive Maintenance is useless because people already have valuable tools, and I don't see a big room for AI here.&lt;/li&gt;
&lt;li&gt;The last is Improved Decision Making and the summary, which puts an end to history and is quite well filled with information for data analysis; I'm in love with this part.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;ChatGPT&lt;/strong&gt;, on the Other side for me, did the same job but a bit better in some points.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;For some reason, &lt;strong&gt;&lt;em&gt;Cost Saving&lt;/em&gt;&lt;/strong&gt; wasn't described in the ChatGPT article, which is a crucial topic for the business and users.&lt;/li&gt;
&lt;li&gt;The overall style is good in both blogs, but ChatGPT tried to use more not common English words, which is an advantage for me as a non-English speaker.&lt;/li&gt;
&lt;li&gt;Most of the topics were similar, that's is good, but &lt;strong&gt;ChatGPT&lt;/strong&gt; make a fascinating point, which &lt;strong&gt;NotionAI didn't mention&lt;/strong&gt; it is the Democratization of Technology. I agree with this topic and say that this one was in my heart, but the thing is that our technologies are limited by the governments, so If you're not friendly to some other government, they can block you from the technologies they own.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Comparison table
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;ChatGPT&lt;/th&gt;
&lt;th&gt;NotionAI&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Introduction&lt;/td&gt;
&lt;td&gt;🥇&lt;/td&gt;
&lt;td&gt;🥇&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Efficiency&lt;/td&gt;
&lt;td&gt;🥇&lt;/td&gt;
&lt;td&gt;🥈&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cost Savings&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;🥇&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Personalization&lt;/td&gt;
&lt;td&gt;🥇&lt;/td&gt;
&lt;td&gt;🥇&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Maintenance&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;🥇&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Improved Decision Making&lt;/td&gt;
&lt;td&gt;🥇&lt;/td&gt;
&lt;td&gt;🥇&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Advancements in Research and Innovation&lt;/td&gt;
&lt;td&gt;🥇&lt;/td&gt;
&lt;td&gt;🥈&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Democratization of Technology&lt;/td&gt;
&lt;td&gt;🥇&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Conclusion&lt;/td&gt;
&lt;td&gt;🥇&lt;/td&gt;
&lt;td&gt;🥇&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;With a small margin, ChatGPT won this battle 🏆&lt;/p&gt;

&lt;p&gt;See you in the next chapter of our battle ChatGPT vs Notion AI 🤹‍♀️&lt;/p&gt;

</description>
      <category>notion</category>
      <category>notionai</category>
      <category>chatgpt</category>
      <category>ai</category>
    </item>
    <item>
      <title>Chat GPT 🆚 Notion AI (Introduction)</title>
      <dc:creator>Hleb Kryshyn</dc:creator>
      <pubDate>Sun, 26 Mar 2023 08:00:00 +0000</pubDate>
      <link>https://dev.to/dealwith/chat-gpt-notion-ai-introduction-1kab</link>
      <guid>https://dev.to/dealwith/chat-gpt-notion-ai-introduction-1kab</guid>
      <description>&lt;p&gt;🤼 Today, I will start a new series of articles comparing two AI models in both functional and usability ways, ChatGPT-4 and Notion AI, in the day-to-day task to understand how they perform in different tasks.&lt;/p&gt;

&lt;p&gt;At the end of each article, we will have a score and, at the end of the series, a summary table for all tasks provided.&lt;/p&gt;

&lt;p&gt;The "Introduction article" will compare usage, prices, and limitations.&lt;/p&gt;

&lt;h2&gt;
  
  
  Overview 📋:
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Usage 🎒&lt;/li&gt;
&lt;li&gt;Language support 👅&lt;/li&gt;
&lt;li&gt;Prices and limitations 🏷️&lt;/li&gt;
&lt;li&gt;Summary 🏁&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Usage
&lt;/h2&gt;

&lt;p&gt;Regarding usage, you can use Notion AI on whatever device you have the notion application, is desktop, web, or mobile, while Chat GPT is a web-based solution. Chat GPT is the solution to go and ask, while in Notion AI, we have a list of predefined things and suggestions to work with the text and page you already have in your working space.&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%2Ftaxurg4r1e77e1jfmh6u.jpg" 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%2Ftaxurg4r1e77e1jfmh6u.jpg" alt="Notion AI features" width="800" height="161"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Language support
&lt;/h2&gt;

&lt;p&gt;💬 &lt;strong&gt;ChatGPT&lt;/strong&gt; supports a wide variety of languages which is 25 languages:&lt;br&gt;
English, Spanish, French, German, Italian, Portuguese, Dutch, Russian, Chinese (Simplified and Traditional), Japanese, Korean, Arabic, Turkish, Danish, Swedish, Norwegian, Finnish, Polish, Czech, Hungarian, Greek, Hebrew, Thai, Indonesian, and Vietnamese.&lt;/p&gt;

&lt;p&gt;It's really helpful when it comes to the usage for translating something, especially if you're doing a multilanguage website, which is easy with current machine translations and can bring more customers to your website.&lt;/p&gt;

&lt;p&gt;🤖 &lt;strong&gt;Notion AI&lt;/strong&gt; supports 13 languages:&lt;br&gt;
English, Korean, Chinese, Japanese, Spanish, Russian, French, Portuguese, German, Italian, Dutch, Indonesian, Filipino, and Vietnamese.&lt;/p&gt;

&lt;p&gt;This is also not a bad result, I would say, because I guess Notion AI have less experience and data to support more languages, but 13 is still a good amount!&lt;/p&gt;

&lt;h2&gt;
  
  
  Prices and limitations
&lt;/h2&gt;

&lt;p&gt;ChatGPT is &lt;strong&gt;&lt;em&gt;20 dollars per month&lt;/em&gt;&lt;/strong&gt;, while Notion AI is &lt;strong&gt;&lt;em&gt;8 dollars per month&lt;/em&gt;&lt;/strong&gt;, paid annually. What is a big plus is that Notion AI is already included in your favourite tool and seamlessly integrated into your system, but if you're not so much into Notion, it can become one more; to use instead of just jumping and using the responses of the chat.&lt;/p&gt;

&lt;p&gt;If you're located in Belarus, Russia, or some other countries under sanctions, it can be easier to use Notion AI because it doesn't require a VPN to use the AI.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;At the end of this article, I can say that both tools got the same score so this fight wouldn't be easy!&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;ChatGPT&lt;/th&gt;
&lt;th&gt;Notion AI&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Usage&lt;/td&gt;
&lt;td&gt;🥇&lt;/td&gt;
&lt;td&gt;🥇&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Language support&lt;/td&gt;
&lt;td&gt;🥇&lt;/td&gt;
&lt;td&gt;🥈&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Prices and limitations&lt;/td&gt;
&lt;td&gt;🥈&lt;/td&gt;
&lt;td&gt;🥇&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Cover design by &lt;a href="https://www.behance.net/jumazur?tracking_source=search_users|julia%20mazur" rel="noopener noreferrer"&gt;Julia Mazur&lt;/a&gt;&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://affiliate.notion.so/y7zb9kqleznk" rel="noopener noreferrer"&gt;Notion&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://apps.apple.com/us/app/one-markdown/id1507139439" rel="noopener noreferrer"&gt;OneMarkdown&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://chat.openai.com" rel="noopener noreferrer"&gt;ChatGPT&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>chatgpt</category>
      <category>notionai</category>
      <category>ai</category>
      <category>notion</category>
    </item>
    <item>
      <title>Compound components pattern for creating reusable Rating component</title>
      <dc:creator>Hleb Kryshyn</dc:creator>
      <pubDate>Mon, 13 Feb 2023 15:00:00 +0000</pubDate>
      <link>https://dev.to/dealwith/compound-components-pattern-for-creating-reusable-rating-component-m07</link>
      <guid>https://dev.to/dealwith/compound-components-pattern-for-creating-reusable-rating-component-m07</guid>
      <description>&lt;h3&gt;
  
  
  👋 Hey folks
&lt;/h3&gt;

&lt;p&gt;This article will give you an explanation of a "Compound components" pattern.&lt;/p&gt;

&lt;h3&gt;
  
  
  🤔 Why should I know about the "Compound components"?
&lt;/h3&gt;

&lt;p&gt;"Compound components" is a pattern that helps to create reusable components dependent on each other. Such a pattern helps to achieve better isolation. This approach allows developers to easily create dynamic and interactive user interfaces while keeping the code clean and organized. This is just one of the many benefits of using React and compound components in web development.&lt;/p&gt;

&lt;h3&gt;
  
  
  👨‍🔬 Could you show me an image explanation?
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;Rating&lt;/code&gt; - component should contain logic for enormous stars and be easily scalable and reusable.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;RatingItem&lt;/code&gt; - component should consume the logic from the &lt;code&gt;Rating&lt;/code&gt; component and don't contain any styling, to reuse across different projects or designs. Because the UI design can be changed in the future, and your star will become a smile or something else.&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%2Fpi3p86yf907debmgbz1f.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%2Fpi3p86yf907debmgbz1f.png" alt="Rating component top level explanation" width="800" height="366"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  👨‍🔬 Ok, before implementing, let me explain the &lt;code&gt;Rating&lt;/code&gt; components deeper!
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;What should we store in the &lt;code&gt;Rating&lt;/code&gt; component?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Rating state&lt;/strong&gt;, in our case, ranges from 1 to 5.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hovered boolean&lt;/strong&gt; to know if our user hovers over our rating component?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hovered state&lt;/strong&gt;, from 1 to 5, to create a good UI experience.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;What will be inside the &lt;code&gt;RatingItem&lt;/code&gt; component?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No styling because the design can be different in projects, and it will be a pain to change the &lt;code&gt;RatingItem&lt;/code&gt; each time we have a new design.&lt;/li&gt;
&lt;li&gt;Different handlers, like &lt;code&gt;handleClick&lt;/code&gt; or &lt;code&gt;handleMouseLeave&lt;/code&gt;, depending on your needs.&lt;/li&gt;
&lt;/ul&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%2F8679z6acw6zft66polvf.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%2F8679z6acw6zft66polvf.png" alt="Compound Components implementation structure" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  👨‍💻 Let's code it!
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;folder structure

contexts/RatingContext.ts
providers/RatingProvider.ts
components/Rating.tsx
components/RatingItem.tsx
components/Feedback.tsx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  1) Creating &lt;code&gt;Context&lt;/code&gt; and &lt;code&gt;Provider&lt;/code&gt; for a &lt;code&gt;Rating&lt;/code&gt; component.
&lt;/h4&gt;

&lt;p&gt;&lt;code&gt;contexts/RatingContext.ts&lt;/code&gt;&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;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;RatingContext&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createContext&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;rating&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="na"&gt;setRating&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;_rating&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&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="na"&gt;hoverRating&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="na"&gt;setHoverRating&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;_rating&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&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="na"&gt;isHovering&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="na"&gt;setIsHovering&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;_isHovering&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;boolean&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;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;providers/RatingProvider.ts&lt;/code&gt;&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;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;RatingProvider&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;RatingContext&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Provider&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We're creating &lt;code&gt;Context&lt;/code&gt; because we need to pass information from &lt;code&gt;Rating&lt;/code&gt; to &lt;code&gt;RatingItem&lt;/code&gt;, whatever nesting it will be.&lt;/p&gt;

&lt;h4&gt;
  
  
  2) Creating a &lt;code&gt;Rating&lt;/code&gt; component with the basic state needed.
&lt;/h4&gt;

&lt;p&gt;&lt;code&gt;components/Rating/Rating.tsx&lt;/code&gt;&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="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Props&lt;/span&gt; &lt;span class="o"&gt;=&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;ReactNode&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;Rating&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;FC&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Props&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&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;=&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;rating&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setRating&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// used to store the current rating&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;hoverRating&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setHoverRating&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// store information about the current hovered state&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;isHovering&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setIsHovering&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="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// information about is the rating hovered right now or not&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;contextValue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useMemo&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="p"&gt;({&lt;/span&gt;
      &lt;span class="nx"&gt;rating&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;hoverRating&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;isHovering&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;setRating&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;setHoverRating&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;setIsHovering&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;rating&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;hoverRating&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;isHovering&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;RatingProvider&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;contextValue&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;children&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;/RatingProvider&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  3) Let's create a hook to consume the &lt;code&gt;RatingContext&lt;/code&gt;
&lt;/h4&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;useContext&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;RatingContext&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;../../contexts/RatingContext&lt;/span&gt;&lt;span class="dl"&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;useRatingContext&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;context&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useContext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;RatingContext&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;context&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;useRatingContext must be used within a RatingContext&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;context&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;📝 &lt;strong&gt;Note:&lt;/strong&gt; Here, we have a "Compound components" logic. The idea is that this hook will throw an error wherever we try to use the component with this hook outside of the &lt;code&gt;Rating&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4&gt;
  
  
  4) Creating &lt;code&gt;&amp;lt;RatingItem /&amp;gt;&lt;/code&gt; component.
&lt;/h4&gt;

&lt;p&gt;&lt;code&gt;components/RatingItem.tsx&lt;/code&gt;&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="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Props&lt;/span&gt; &lt;span class="o"&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;number&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;JSX&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Element&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;RatingItem&lt;/span&gt; &lt;span class="o"&gt;=&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="nx"&gt;children&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="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;setRating&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;rating&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;hoverRating&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setHoverRating&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setIsHovering&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useRatingContext&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;span&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;cursor-pointer&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;cloneElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;needed_props_here&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;/span&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;ul&gt;
&lt;li&gt;Prop &lt;code&gt;value&lt;/code&gt; is used to pass information about what value of the rating will represent your &lt;code&gt;RatingItem&lt;/code&gt; like 1, 2, or 0.5, depending on your needs.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;useRatingContext&lt;/code&gt; gives access to provider values.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;{cloneElement(children, { neededPropsHere })}&lt;/code&gt; will provide to your icon all props that are needed in the future to control this icon UI state. We're using here the &lt;a href="https://beta.reactjs.org/reference/react/cloneElement" rel="noopener noreferrer"&gt;cloneElement API&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  5) Improving &lt;code&gt;&amp;lt;RatingItem /&amp;gt;&lt;/code&gt; component by adding additional handlers.
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;RatingItem&lt;/span&gt; &lt;span class="o"&gt;=&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="nx"&gt;children&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="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;setRating&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;rating&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;hoverRating&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setHoverRating&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setIsHovering&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useRatingContext&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

  &lt;span class="c1"&gt;// new code&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleMouseEnter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;setHoverRating&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="nf"&gt;setIsHovering&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleMouseLeave&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;setHoverRating&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="nf"&gt;setIsHovering&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleClick&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;rating&lt;/span&gt; &lt;span class="o"&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="nf"&gt;setRating&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

      &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nf"&gt;setRating&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;isCurrentRating&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;rating&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;isHoveredRating&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;hoverRating&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;isRatingNotSet&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;rating&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;isFilled&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;isRatingNotSet&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;isCurrentRating&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;isHoveredRating&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;span&lt;/span&gt;
      &lt;span class="nx"&gt;onMouseEnter&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;handleMouseEnter&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="nx"&gt;onMouseLeave&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;handleMouseLeave&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;handleClick&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;cursor-pointer&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
    &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="c1"&gt;// end of new code&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;cloneElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;isFilled&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;isChoose&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;isCurrentRating&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;/span&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;ul&gt;
&lt;li&gt;We added code to handle the mouse events &lt;code&gt;handleClick&lt;/code&gt;, &lt;code&gt;handleMouseLeave&lt;/code&gt;, and &lt;code&gt;handleMouseEnter&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;We added constants &lt;code&gt;isCurrentRating&lt;/code&gt;, &lt;code&gt;isHoveredRating&lt;/code&gt;, &lt;code&gt;isRatingNotSet&lt;/code&gt;, and &lt;code&gt;isFilled&lt;/code&gt;, which will be used to implement the needed UI pattern. &lt;strong&gt;&lt;em&gt;This part can vary depending on your design!&lt;/em&gt;&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  6) We created almost all the needed logic to display our rating.
&lt;/h4&gt;

&lt;p&gt;&lt;code&gt;components/Feedback/feedback.tsx&lt;/code&gt;&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;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Feedback&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Rating&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;div&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;styles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;rating&lt;/span&gt;&lt;span class="p"&gt;}&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;RatingItem&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="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;IconVeryBad&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="sr"&gt;/RatingItem&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;RatingItem&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="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;}&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;IconBad&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="sr"&gt;/RatingItem&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;RatingItem&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="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;}&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;IconNeutral&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="sr"&gt;/RatingItem&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;RatingItem&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="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;}&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;IconGood&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="sr"&gt;/RatingItem&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;RatingItem&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="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;}&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;IconVeryGood&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="sr"&gt;/RatingItem&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/Rating&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;h4&gt;
  
  
  7) But what if we need to know in the &lt;code&gt;Feedback&lt;/code&gt; component what is the rating right now?
&lt;/h4&gt;

&lt;p&gt;&lt;code&gt;components/Rating.tsx&lt;/code&gt;&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="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Props&lt;/span&gt; &lt;span class="o"&gt;=&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;ReactNode&lt;/span&gt;
  &lt;span class="nx"&gt;onRatingChange&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;rating&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&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;void&lt;/span&gt; &lt;span class="c1"&gt;// new prop onRatingChange&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;Rating&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;FC&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Props&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&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="nx"&gt;onRatingChange&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;rating&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setRating&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;hoverRating&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setHoverRating&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;isHovering&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setIsHovering&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="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="nx"&gt;contextValue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useMemo&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="p"&gt;({&lt;/span&gt;
      &lt;span class="nx"&gt;rating&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;hoverRating&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;isHovering&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;setRating&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;setHoverRating&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;setIsHovering&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;rating&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;hoverRating&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;isHovering&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
    &lt;span class="nx"&gt;onRatingChange&lt;/span&gt;&lt;span class="p"&gt;?.(&lt;/span&gt;&lt;span class="nx"&gt;rating&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// a prop function be called each time rating is changing&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;rating&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;RatingProvider&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;contextValue&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;children&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;/RatingProvider&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;onRatingChange&lt;/code&gt; - a function that will be called when the user changes the rating.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  8) Usage of the &lt;code&gt;Rating&lt;/code&gt; component
&lt;/h4&gt;

&lt;p&gt;&lt;code&gt;component/RatingFeedback.tsx&lt;/code&gt;&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;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;RatingFeedback&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;isShowText&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setShowText&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="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="nx"&gt;handleRatingChange&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;rating&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&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;rating&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;setShowText&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="nf"&gt;setRating&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;rating&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="nf"&gt;setShowText&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="nf"&gt;setRating&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="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;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Rating&lt;/span&gt; &lt;span class="nx"&gt;onRatingChange&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;handleRatingChange&lt;/span&gt;&lt;span class="p"&gt;}&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;div&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;flex justify-between w-full pointer-events-auto background-color-300 mt-4 max-w-[300px]&lt;/span&gt;&lt;span class="dl"&gt;"&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;RatingItem&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="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;IconVeryBad&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="sr"&gt;/RatingItem&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;RatingItem&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="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;}&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;IconBad&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="sr"&gt;/RatingItem&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;RatingItem&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="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;}&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;IconNeutral&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="sr"&gt;/RatingItem&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;RatingItem&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="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;}&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;IconGood&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="sr"&gt;/RatingItem&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;RatingItem&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="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;}&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;IconVeryGood&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="sr"&gt;/RatingItem&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/Rating&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;isShowText&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&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;label&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="nx"&gt;Please&lt;/span&gt; &lt;span class="nx"&gt;write&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="nx"&gt;us&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;textarea&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="sr"&gt;/label&lt;/span&gt;&lt;span class="err"&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="sr"&gt;/&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;ul&gt;
&lt;li&gt;
&lt;code&gt;handleRatingChange&lt;/code&gt; is responsible for showing a text field when the user chooses a rating&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  🏁 Summary
&lt;/h3&gt;

&lt;p&gt;In this article, we demonstrated the use of "Compound components" for creating a rating system using React. Compound components allow you to create complex UI components by combining simple and reusable components. This approach improves code organization, making it easier to maintain and extend. The example we used showed how to create a rating system that is both user-friendly and customizable.&lt;/p&gt;

&lt;p&gt;To test the code and see the example in action, you can follow the link: &lt;a href="https://codesandbox.io/p/sandbox/compound-components-for-rating-y6getu" rel="noopener noreferrer"&gt;https://codesandbox.io/p/sandbox/compound-components-for-rating-y6getu&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>watercooler</category>
    </item>
    <item>
      <title>Advanced enterprise localisation process with Lingui, Locize, GitHub Actions, Docker, React</title>
      <dc:creator>Hleb Kryshyn</dc:creator>
      <pubDate>Thu, 22 Dec 2022 07:13:04 +0000</pubDate>
      <link>https://dev.to/dealwith/advanced-enterprise-localisation-process-with-lingui-locize-github-actions-docker-react-37g2</link>
      <guid>https://dev.to/dealwith/advanced-enterprise-localisation-process-with-lingui-locize-github-actions-docker-react-37g2</guid>
      <description>&lt;p&gt;I have experience in integrating localisation into three applications of different sizes. In this article, I will share my experience only with the enterprise localisation process. If you are interested in localisation for other project sizes, please share your thoughts in the comments 💭&lt;/p&gt;

&lt;h2&gt;
  
  
  General idea 🚀
&lt;/h2&gt;

&lt;p&gt;The main idea was to have a process allowing developers to do fewer actions and have everything automated in the CI, from uploading to downloading the translations.&lt;br&gt;
We want a source of truth for keys &lt;strong&gt;in the code&lt;/strong&gt; and a source of truth for translations - &lt;strong&gt;a 3rd party translation platform&lt;/strong&gt; (in our case - locize).&lt;/p&gt;
&lt;h2&gt;
  
  
  Choosing front-end library 📚
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Quick Summary:
&lt;/h3&gt;

&lt;p&gt;We choose &lt;a href="https://lingui.js.org/" rel="noopener noreferrer"&gt;lingui&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;
  
  
  Comparison table for front-end libs
&lt;/h3&gt;

&lt;p&gt;First, we should check out the libs for the front end, which will work with our localisation.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Name&lt;/th&gt;
&lt;th&gt;Size (minified + gzipped)&lt;/th&gt;
&lt;th&gt;Dependecies&lt;/th&gt;
&lt;th&gt;Typescript&lt;/th&gt;
&lt;th&gt;Open/Closed issues&lt;/th&gt;
&lt;th&gt;Last publish&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;react-i18next&lt;/td&gt;
&lt;td&gt;6.7kB&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;8%&lt;/td&gt;
&lt;td&gt;8/1044&lt;/td&gt;
&lt;td&gt;a month ago&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;lingui&lt;/td&gt;
&lt;td&gt;7.8kB&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;89%&lt;/td&gt;
&lt;td&gt;20/693&lt;/td&gt;
&lt;td&gt;4 months ago&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;react-intl&lt;/td&gt;
&lt;td&gt;17.8kB&lt;/td&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;td&gt;77%&lt;/td&gt;
&lt;td&gt;12/1686&lt;/td&gt;
&lt;td&gt;4 days ago&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;react-translated&lt;/td&gt;
&lt;td&gt;7.8kB&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;0%&lt;/td&gt;
&lt;td&gt;3/6&lt;/td&gt;
&lt;td&gt;3 years ago&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Also, a big plus was a minimal amount of issues for &lt;code&gt;lingui/react&lt;/code&gt;. Previously I tried &lt;code&gt;react-i18next&lt;/code&gt;, which was good, but we didn't go with it because the feedback from the other organisation members was good. Our application already has system modules that were integrated with &lt;code&gt;lingui&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Here is a detailed article about how to choose the proper library.&lt;/strong&gt;&lt;/p&gt;


&lt;div class="ltag__link"&gt;
  &lt;a href="/dealwith" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&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%2Fuser%2Fprofile_image%2F612527%2F47052a88-d312-42a3-a9cd-21542bd6d08c.JPG" alt="dealwith"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="https://dev.to/dealwith/how-to-choose-the-right-npm-package-in-a-4-steps-42bo" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;How to choose the right NPM package in 4 steps 📦&lt;/h2&gt;
      &lt;h3&gt;Hleb Kryshyn ・ Oct 17 '22&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#npm&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#productivity&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#opensource&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


&lt;h2&gt;
  
  
  Choosing 3rd party localisation service 🗺️
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Quick Summary:
&lt;/h3&gt;

&lt;p&gt;We choose &lt;a href="https://locize.com/" rel="noopener noreferrer"&gt;locize&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Localisation platforms comparison
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;service&lt;/th&gt;
&lt;th&gt;integration&lt;/th&gt;
&lt;th&gt;pricing for 10k/m&lt;/th&gt;
&lt;th&gt;experience for translator&lt;/th&gt;
&lt;th&gt;developer features&lt;/th&gt;
&lt;th&gt;summary&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;locize.com&lt;/td&gt;
&lt;td&gt;good doc, easy&lt;/td&gt;
&lt;td&gt;fluid pricing depends on the usage&lt;/td&gt;
&lt;td&gt;bad UX, hard to collaborate&lt;/td&gt;
&lt;td&gt;versioning, plurals, reach API &amp;amp; CLI&lt;/td&gt;
&lt;td&gt;Unlimited Contributors, Unlimited projects&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;poeditor.com&lt;/td&gt;
&lt;td&gt;GitHub app&lt;/td&gt;
&lt;td&gt;$38.24&lt;/td&gt;
&lt;td&gt;comments, good UI, machine translations&lt;/td&gt;
&lt;td&gt;plurals, versioning, multiple projects&lt;/td&gt;
&lt;td&gt;Unlimited Contributors, Unlimited Projects&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;lokalise.com&lt;/td&gt;
&lt;td&gt;GitHub app&lt;/td&gt;
&lt;td&gt;$230 (only 10 seats included)&lt;/td&gt;
&lt;td&gt;discussions, good UI&lt;/td&gt;
&lt;td&gt;plurals, work with multiple branches&lt;/td&gt;
&lt;td&gt;Really high price with no machine translations, limited seats&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;translation.com&lt;/td&gt;
&lt;td&gt;sync cli/platform&lt;/td&gt;
&lt;td&gt;$0.01/ key active projects $100 $0.005/key archive project $50&lt;/td&gt;
&lt;td&gt;discussions, machine translations, good UI&lt;/td&gt;
&lt;td&gt;plurals&lt;/td&gt;
&lt;td&gt;Promoted by lingui, easy to use, cheap&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;smartling&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;Push you to buy annual, high price for a small number of features&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Сrowdin&lt;/td&gt;
&lt;td&gt;GitHub, Gitlab&lt;/td&gt;
&lt;td&gt;0.01$/key with no available integrations, basic subscription is so limited, you also need additional payments for translation managers&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;good UI, not so hard to use&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;phrase&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;70usd per month for 3 users (100api/request per user monthly)&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;too expensive, most of the features are the same or less as everywhere else&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;em&gt;Minus sign in the table has the meaning of not having a feature or doesn't have enough info about features in the specific service.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;At first glance, I realised there would be little difference in localisation platforms. For our team, the crucial point was to have a good amount of features for a reasonable price and a robust API which would allow us to deeply integrate our CI with a translation platform.&lt;/p&gt;

&lt;h4&gt;
  
  
  Platform locize was chosen for:
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;Fluid pricing systems that depend on the actual usage of the platform&lt;/li&gt;
&lt;li&gt;Good versioning system, which allows you to use a semver versioning system&lt;/li&gt;
&lt;li&gt;Reach API and CLI for a better low-level integration&lt;/li&gt;
&lt;li&gt;Unlimited Contributors and Unlimited projects&lt;/li&gt;
&lt;li&gt;Easy way to integrate with client library - lingui.&lt;/li&gt;
&lt;li&gt;Fast support from the creator&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Upload new keys process 📑
&lt;/h2&gt;

&lt;p&gt;Here is a sequence diagram which explains the whole process of uploading. Your detailed implementation can be different according to your project tools.&lt;br&gt;
If you don't know what is sequence diagram you can check out this &lt;a href="https://mermaid-js.github.io/mermaid/#/sequenceDiagram" rel="noopener noreferrer"&gt;documentation in mermaid&lt;/a&gt;&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%2Fzudl4xw63doju1kpgnn9.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%2Fzudl4xw63doju1kpgnn9.png" alt="Upload new keys process" width="800" height="696"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Implementation details
&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;This section will describe some implementation details inside our project. If you're using another tech stack, feel free to skip it and go on.&lt;/em&gt;&lt;/p&gt;
&lt;h4&gt;
  
  
  Step 1
&lt;/h4&gt;

&lt;p&gt;We only trigger the upload process in the &lt;code&gt;origin/main&lt;/code&gt; branch when merging the PR.&lt;/p&gt;
&lt;h4&gt;
  
  
  Step 2
&lt;/h4&gt;

&lt;p&gt;Our project is a monorepo containing several front-ends which need localisation. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://rushjs.io/" rel="noopener noreferrer"&gt;Rush&lt;/a&gt; provides an excellent way to understand what project is changed by running &lt;code&gt;rush change&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;After that, we pick these projects inside the CI step and analyse the &lt;a href="https://docs.npmjs.com/cli/v9/configuring-npm/package-json#config" rel="noopener noreferrer"&gt;package.json of this project for the &lt;code&gt;localisation: true&lt;/code&gt; flag&lt;/a&gt;. We put a flag inside our front-end project for a faster localisation check. This config section is rarely used, but so cool to know about.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;package.json&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="p"&gt;...,&lt;/span&gt;
  &lt;span class="nx"&gt;devDependencies&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{...},&lt;/span&gt;
  &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;localisation&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Step 3
&lt;/h4&gt;

&lt;p&gt;To extract the translations keys from the code, we used &lt;a href="https://lingui.js.org/ref/cli.html#lingui-cli-extract" rel="noopener noreferrer"&gt;lingui extract&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;lingui extract --clean&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This tool works as we need it - developers do nothing, and everything is automated. He/she is just putting translation keys into the code, and this command will automatically search for the keys and put them into all translation files if the key doesn't exist there yet.&lt;/p&gt;

&lt;h4&gt;
  
  
  Version calculation
&lt;/h4&gt;

&lt;p&gt;We're calculating a future version and returning a major or minor version.&lt;/p&gt;

&lt;h4&gt;
  
  
  Steps 4-9
&lt;/h4&gt;

&lt;p&gt;We upgrade a minor version when developers add new keys to the translations.&lt;/p&gt;

&lt;p&gt;These steps are done by manipulating the &lt;a href="https://docs.locize.com/integration/api" rel="noopener noreferrer"&gt;Locize API&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Steps 10-14
&lt;/h4&gt;

&lt;p&gt;When a developer removes translation keys, we're upgrading a major version.&lt;/p&gt;

&lt;p&gt;These steps are done by manipulating the &lt;a href="https://docs.locize.com/integration/api" rel="noopener noreferrer"&gt;Locize API&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Download new keys process 📲
&lt;/h2&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%2F8tmq3xctsclvq1f5zfle.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%2F8tmq3xctsclvq1f5zfle.png" alt="Download new keys process" width="800" height="696"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Implementation details
&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;This section will describe some implementation details inside our project. If you're using another tech stack, feel free to skip it and go further.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Most steps are part of the &lt;code&gt;download-localisation.sh&lt;/code&gt; script.&lt;/p&gt;

&lt;h4&gt;
  
  
  Step 1
&lt;/h4&gt;

&lt;p&gt;The developer pushes code to the remote repository.&lt;/p&gt;

&lt;h4&gt;
  
  
  Step 2
&lt;/h4&gt;

&lt;p&gt;Inside Github CI, we're building a docker image of the application.&lt;/p&gt;

&lt;h4&gt;
  
  
  Step 3
&lt;/h4&gt;

&lt;p&gt;We run the image with environment variables.&lt;/p&gt;

&lt;p&gt;Useful env variables were:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Translation version&lt;/strong&gt;. For the different dev environments, we used different translation versions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Project id&lt;/strong&gt; from locize. As I wrote, we had several projects inside one repository, so we need several in locize. Also, we need our script to be reusable across the organisation.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Namespace.&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  Step 4
&lt;/h4&gt;

&lt;p&gt;This part of the download-localisation script is responsible for pulling languages for the project.&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="nv"&gt;LANGUAGES&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;
  curl &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="s2"&gt;"https://api.locize.app/languages/&lt;/span&gt;&lt;span class="nv"&gt;$LOCIZE_PROJECT_ID&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  | jq &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="s1"&gt;'keys | join(" ")'&lt;/span&gt;
&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Step 5
&lt;/h4&gt;

&lt;p&gt;Code piece which helps us to download translations&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="k"&gt;for &lt;/span&gt;language &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nv"&gt;$LANGUAGES&lt;/span&gt;
&lt;span class="k"&gt;do
    &lt;/span&gt;&lt;span class="nb"&gt;printf&lt;/span&gt; &lt;span class="s2"&gt;"Downloading translation for &lt;/span&gt;&lt;span class="nv"&gt;$language&lt;/span&gt;&lt;span class="s2"&gt;..."&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$TRANSLATIONS_DIR&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;$language&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;
    &lt;span class="k"&gt;then
        &lt;/span&gt;&lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-fr&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$TRANSLATIONS_DIR&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;$language&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
    &lt;span class="k"&gt;fi

    &lt;/span&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$TRANSLATIONS_DIR&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;$language&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

    curl &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$TRANSLATIONS_DIR&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;$language&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;$LOCIZE_NAMESPACE&lt;/span&gt;&lt;span class="s2"&gt;.json"&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$LOCIZE_API_BASE&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;$LOCIZE_PROJECT_ID&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;$LOCIZE_VERSION&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;$language&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;$LOCIZE_NAMESPACE&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

    &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Done"&lt;/span&gt;
&lt;span class="k"&gt;done&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Step 6
&lt;/h4&gt;

&lt;p&gt;Loading the translations is happening with the help of &lt;code&gt;@lingui/remote-loader&lt;/code&gt;. This remote loader wasn't listed in the lingui documentation but exists in npm and the codebase. Finding this module took some time, so right now, you can use that time wisely!&lt;/p&gt;

&lt;h2&gt;
  
  
  Finish 🏁
&lt;/h2&gt;

&lt;p&gt;I hope you enjoyed reading this article. Please leave your thoughts about such localisation design architecture.&lt;/p&gt;

&lt;p&gt;Cover design by: &lt;a href="https://www.behance.net/jumazur" rel="noopener noreferrer"&gt;Julia Mazur&lt;/a&gt;&lt;/p&gt;

</description>
      <category>react</category>
      <category>localisation</category>
      <category>architecture</category>
      <category>docker</category>
    </item>
    <item>
      <title>How to choose the right NPM package in 4 steps 📦</title>
      <dc:creator>Hleb Kryshyn</dc:creator>
      <pubDate>Mon, 17 Oct 2022 00:11:28 +0000</pubDate>
      <link>https://dev.to/dealwith/how-to-choose-the-right-npm-package-in-a-4-steps-42bo</link>
      <guid>https://dev.to/dealwith/how-to-choose-the-right-npm-package-in-a-4-steps-42bo</guid>
      <description>&lt;p&gt;Hey, maybe you have been searching for the right library for your needs several times. In this article, I will present my algorithm to find suitable and share appropriate resources. For example, I will try to find a good library for front-end localisation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Let's find and create a list of libraries 📋
&lt;/h2&gt;

&lt;p&gt;I post some of them here, but it's good to have more options.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;react-i18next&lt;/li&gt;
&lt;li&gt;lingui&lt;/li&gt;
&lt;li&gt;react-intl&lt;/li&gt;
&lt;li&gt;react-translated&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Resources: &lt;a href="https://bestofjs.org/" rel="noopener noreferrer"&gt;bestofjs&lt;/a&gt;, &lt;a href="https://openbase.com/" rel="noopener noreferrer"&gt;openbase&lt;/a&gt;, articles on the topic.&lt;/p&gt;

&lt;h2&gt;
  
  
  Check the documentation 📑
&lt;/h2&gt;

&lt;p&gt;It's an obvious tip, but not everybody understands what to check. You should understand your business requirements and then go to the doc to see if the libs contain all of the features you need and support a translation format for your project.&lt;/p&gt;

&lt;h2&gt;
  
  
  Take a look at the project source code 🏢
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Try to understand who maintains the project. If even one repo is less popular, it will have a founder who understands the problems of other frameworks in the industry and solves them more efficiently.&lt;/li&gt;
&lt;li&gt;Check for the issues, how they are reviewed, and are the community actively collaborates to improve the package.&lt;/li&gt;
&lt;li&gt;Check the project insights page. It's a place where you will find more statistical data.
&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%2Fvasfmhu5s2qwe5s4buda.png" alt="Lingui project insights" width="800" height="634"&gt;
&lt;/li&gt;
&lt;li&gt;If you cannot find a needed feature in the documentation, it's possible that authors forgot to add it, or didn't have enough time for it, so it's definitely best to go to the source files and check them.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Create a comparison table ⛳️
&lt;/h2&gt;

&lt;p&gt;It's an excellent way to structure all information into one table.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Name&lt;/th&gt;
&lt;th&gt;Size (minified + gzipped)&lt;/th&gt;
&lt;th&gt;Dependecies&lt;/th&gt;
&lt;th&gt;Typescript&lt;/th&gt;
&lt;th&gt;Open/Closed issues&lt;/th&gt;
&lt;th&gt;Last publish&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;react-i18next&lt;/td&gt;
&lt;td&gt;6.7kB&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;8%&lt;/td&gt;
&lt;td&gt;8/1044&lt;/td&gt;
&lt;td&gt;a month ago&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;lingui&lt;/td&gt;
&lt;td&gt;7.8kB&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;89%&lt;/td&gt;
&lt;td&gt;20/693&lt;/td&gt;
&lt;td&gt;4 months ago&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;react-intl&lt;/td&gt;
&lt;td&gt;17.8kB&lt;/td&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;td&gt;77%&lt;/td&gt;
&lt;td&gt;12/1686&lt;/td&gt;
&lt;td&gt;4 days ago&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;react-translated&lt;/td&gt;
&lt;td&gt;7.8kB&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;0%&lt;/td&gt;
&lt;td&gt;3/6&lt;/td&gt;
&lt;td&gt;3 years ago&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;To create this table I used &lt;a href="https://bundlephobia.com/" rel="noopener noreferrer"&gt;bundlephobia&lt;/a&gt;, &lt;a href="https://npmtrends.com/" rel="noopener noreferrer"&gt;npmtrends&lt;/a&gt;, &lt;a href="https://snyk.io/" rel="noopener noreferrer"&gt;snyk&lt;/a&gt;, github projects page.&lt;/p&gt;

&lt;h2&gt;
  
  
  Is it easy to integrate? 🤓
&lt;/h2&gt;

&lt;p&gt;In our case, for the front-end localisation lib, we will check several points:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Is it easy to integrate into your project? Maybe your monorepo already has some localisation dependencies&lt;/li&gt;
&lt;li&gt;Does it support your front-end framework&lt;/li&gt;
&lt;li&gt;After the integration, it's good to measure performance changes&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Finally 🎉
&lt;/h2&gt;

&lt;p&gt;You will have a bigger picture of what is going on with your npm packages. Have fun!&lt;/p&gt;

</description>
      <category>npm</category>
      <category>productivity</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Debug controllers and debug flow in VSCode</title>
      <dc:creator>Hleb Kryshyn</dc:creator>
      <pubDate>Fri, 12 Aug 2022 16:18:00 +0000</pubDate>
      <link>https://dev.to/dealwith/debug-controllers-and-debug-flow-in-vscode-43a3</link>
      <guid>https://dev.to/dealwith/debug-controllers-and-debug-flow-in-vscode-43a3</guid>
      <description>&lt;p&gt;Hey, hey 👋 After we have learned about how to configure our debugger, let's talk more about the actual debugging controllers 🕹 &lt;/p&gt;

&lt;h2&gt;
  
  
  Breakpoints
&lt;/h2&gt;

&lt;p&gt;We will put some breakpoints&lt;br&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%2Fdtrbmscdb837cv7p48of.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%2Fdtrbmscdb837cv7p48of.png" alt="Button component with breakpoint" width="800" height="155"&gt;&lt;/a&gt;&lt;br&gt;
 As you see, we put a breakpoint on &lt;strong&gt;line 12&lt;/strong&gt;, so we will be able to receive a context of our &lt;code&gt;props&lt;/code&gt;.&lt;br&gt;
After that, you restart the page and see in the run &amp;amp; debug section of the &lt;code&gt;VSCode&lt;/code&gt; the following structure. We will talk more about this section later.&lt;br&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%2F7mzdq09ly4fvsjv6ino1.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%2F7mzdq09ly4fvsjv6ino1.png" alt="Run &amp;amp; Debug menu in VSCode" width="800" height="2115"&gt;&lt;/a&gt;&lt;br&gt;
On your screen, near the breakpoint will appear a yellow outline, which means that your code stopped its execution at this line&lt;br&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%2Fhmkyvuoa1liv77w1iwyg.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%2Fhmkyvuoa1liv77w1iwyg.png" alt="Stop execution on a breakpoint" width="800" height="175"&gt;&lt;/a&gt;&lt;br&gt;
We will also get controllers:&lt;br&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%2Fmxe8m4953d3ojnhl791r.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%2Fmxe8m4953d3ojnhl791r.png" alt="Debug controllers VSCode" width="354" height="64"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Continue&lt;/strong&gt; – An action to take in the debugger that will continue execution until the next breakpoint is reached or the program exits.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Step over&lt;/strong&gt; – An action to take in the debugger that will step over a given line. The function will be executed if the string contains a function, and the result is returned without debugging each line.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Step In&lt;/strong&gt; – An action to take in the debugger. If the line does not contain a function, it behaves the same as "step over" but if it does, the debugger will enter the called function and continue line-by-line debugging there.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Step out&lt;/strong&gt; – An action in the debugger that returns to the line where the current function was called.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Restart&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Stop&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;
  
  
  Controller demo
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Continue
&lt;/h3&gt;

&lt;p&gt;&lt;iframe src="https://player.vimeo.com/video/738961049" width="710" height="399"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;With "Continue", we can resume debugging to the next breakpoint you put previously.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step over
&lt;/h3&gt;

&lt;p&gt;&lt;iframe src="https://player.vimeo.com/video/738992294" width="710" height="399"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;"Step over" functionality helps us to go to the following execution line without putting a new breakpoint.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step in
&lt;/h3&gt;

&lt;p&gt;&lt;iframe src="https://player.vimeo.com/video/739001401" width="710" height="399"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;"Step in" gives us a superpower to traverse up&amp;amp;down in a function execution and see the function's return values in a variables section.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step out
&lt;/h3&gt;

&lt;p&gt;&lt;iframe src="https://player.vimeo.com/video/739001056" width="710" height="399"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;I'm happy that we're now familiar with essential debugging tools and ready for a new journey to something more advanced! 🚀🚀🚀&lt;/p&gt;

</description>
      <category>vscode</category>
      <category>debug</category>
      <category>react</category>
      <category>node</category>
    </item>
    <item>
      <title>Front-end Developer roadmap</title>
      <dc:creator>Hleb Kryshyn</dc:creator>
      <pubDate>Sun, 15 May 2022 17:11:31 +0000</pubDate>
      <link>https://dev.to/dealwith/front-end-developer-roadmap-2gi0</link>
      <guid>https://dev.to/dealwith/front-end-developer-roadmap-2gi0</guid>
      <description>&lt;h5&gt;
  
  
  Hey folks 👋
&lt;/h5&gt;

&lt;p&gt;This article will take an eye on one of the exciting topics suitable for every developer level. In addition, I will share a valuable resource for each step of a roadmap that I used before to learn the Front-end.&lt;/p&gt;

&lt;p&gt;I've shared some books here, but everybody knows that books become outdated too fast in a developing world, so to buy them or not is your decision.&lt;/p&gt;

&lt;h3&gt;
  
  
  HTML, CSS 👨‍🎨
&lt;/h3&gt;

&lt;p&gt;The basic level, which sometimes newbies miss 😉&lt;br&gt;
The real foundation I've got in a book &lt;strong&gt;CSS3: The Missing Manual&lt;/strong&gt;, and most of the time, my recommendation is to search for a beautiful and challenging design frames on the internet and try to do them, or a lot of them you can find for free in  &lt;a href="https://www.figma.com/community" rel="noopener noreferrer"&gt;Figma community&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Resources:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://code-basics.com/" rel="noopener noreferrer"&gt;Code basics&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.amazon.com/gp/product/B013VQ7N2M/ref=dbs_a_def_rwt_bibl_vppi_i0" rel="noopener noreferrer"&gt;CSS: The Missing Manual&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://flexboxfroggy.com/" rel="noopener noreferrer"&gt;Flex froggy&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://cssgridgarden.com/" rel="noopener noreferrer"&gt;Grid Garden&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTML" rel="noopener noreferrer"&gt;MDN HTML&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS" rel="noopener noreferrer"&gt;MDN CSS&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  JavaScript ❤️
&lt;/h3&gt;

&lt;p&gt;The foundation of the Web.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://javascript.info/" rel="noopener noreferrer"&gt;Best JavaScript book&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.amazon.com/JavaScript-Good-Parts-Douglas-Crockford/dp/0596517742" rel="noopener noreferrer"&gt;JavaScript: The Good Parts&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  React ⚛️
&lt;/h3&gt;

&lt;p&gt;Really in love with this framework, but wanna try &lt;strong&gt;Svelte&lt;/strong&gt; and &lt;strong&gt;WebComponents&lt;/strong&gt;.&lt;br&gt;
Resources: &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://reactjs.org/" rel="noopener noreferrer"&gt;Documentation - all learning materials you can find here&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://egghead.io/" rel="noopener noreferrer"&gt;Egghead&lt;/a&gt; You can find a lot of good courses here for free, but if you reach, you can even buy a PRO version🤴)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.amazon.com/Learning-React-Functional-Development-Redux/dp/1491954620" rel="noopener noreferrer"&gt;Learning React Functional Development&lt;/a&gt; - can be outdated right now, but still, you can find here some good techniques.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Typescript 🏢
&lt;/h3&gt;

&lt;p&gt;For several years I didn't say a project without TS 🫡&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;a href="https://www.typescriptlang.org/" rel="noopener noreferrer"&gt;Documentation is always the best resource&lt;/a&gt; 😄&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/typescript-cheatsheets/react" rel="noopener noreferrer"&gt;React + TS cheatsheet&lt;/a&gt; - this great cheatsheet I recommend almost to everyone who is doing React+TS&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Docker
&lt;/h3&gt;

&lt;p&gt;It is an essential technology in the middle-size project and enterprise development.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://docs.docker.com/get-started/overview/#docker-engine" rel="noopener noreferrer"&gt;Info about docker engine&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.freecodecamp.org/news/a-beginner-friendly-introduction-to-containers-vms-and-docker-79a9e3e119b/" rel="noopener noreferrer"&gt;Introduction to containers&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://itnext.io/getting-started-with-docker-1-b4dc83e64389" rel="noopener noreferrer"&gt;Best article about Docker Anatomy&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;These three resources gave me a basic understanding. For further information, I recommend you to learn through a docker website.&lt;/p&gt;

&lt;h3&gt;
  
  
  Algorithms
&lt;/h3&gt;

&lt;p&gt;In Front-end development, you don't need to know all algorithms, but it's good to learn some basics.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;a href="https://www.amazon.com/Grokking-Algorithms-illustrated-programmers-curious/dp/1617292230/ref=sr_1_1?keywords=Grokking-Algorithms&amp;amp;qid=1652626099&amp;amp;sr=8-1" rel="noopener noreferrer"&gt;Grokking Algorithms&lt;/a&gt; can give you good fundamentals&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.coursera.org/learn/algorithms-part1" rel="noopener noreferrer"&gt;Free course from Princeton&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Testing
&lt;/h3&gt;

&lt;p&gt;A valuable part of the development process, which is good to know.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://jestjs.io/" rel="noopener noreferrer"&gt;Jest&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.cypress.io/" rel="noopener noreferrer"&gt;Cypress&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://testingjavascript.com/" rel="noopener noreferrer"&gt;testingjavascript from Kent&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If you don't have a computer right now, it seems like you share my first steps because I started to learn programming without a laptop, so I would recommend starting with a mobile app called &lt;a href="https://www.sololearn.com/home" rel="noopener noreferrer"&gt;SoloLearn&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;And of course, one of the most excellent places to learn something new is YouTube 🎥&lt;/p&gt;

&lt;p&gt;Share your best resources for Front-end developers in the comments 🥇&lt;/p&gt;

&lt;p&gt;Cover design by &lt;a href="https://www.linkedin.com/in/julia-mazur-99251a1a2/" rel="noopener noreferrer"&gt;Julia Mazur&lt;/a&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>roadmap</category>
      <category>webdev</category>
    </item>
    <item>
      <title>React debugging in VSCode</title>
      <dc:creator>Hleb Kryshyn</dc:creator>
      <pubDate>Sun, 08 May 2022 11:52:27 +0000</pubDate>
      <link>https://dev.to/dealwith/react-debugging-in-vscode-1c0f</link>
      <guid>https://dev.to/dealwith/react-debugging-in-vscode-1c0f</guid>
      <description>&lt;p&gt;Welcome to the second article about debugging if you're struggling with debugging, you're in the right place 😉&lt;/p&gt;

&lt;p&gt;📚 Minute of theory.&lt;/p&gt;

&lt;p&gt;There are 2 basic types of debugging:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Attach (means you're attaching to an already running process)&lt;/li&gt;
&lt;li&gt;Launch - means you're launching a new process and attaching to it. It can be a headless chrome or anything else)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;After some basic understanding, let's jump to the actual configuration.&lt;/p&gt;

&lt;p&gt;1) Add a configuration object inside your array of configurations in &lt;code&gt;.vscode/launch.json&lt;/code&gt; in the project's root.&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;"configurations"&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;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Launch Chrome"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"request"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"launch"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"chrome"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"http://localhost:8080"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;localhost&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;where&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;we&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;will&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;launch&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;our&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;front-end&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"webRoot"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"${workspaceFolder}"&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;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;blockquote&gt;
&lt;p&gt;💡 &lt;strong&gt;Tip:&lt;/strong&gt;  You can generate the same code by pressing the "Add configuration" button in VSCode bottom right corner.&lt;br&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%2F1knscou070wy1dri2tbg.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%2F1knscou070wy1dri2tbg.png" alt="Add configuration button" width="278" height="72"&gt;&lt;/a&gt;&lt;br&gt;
After clicking the button, you will see a context menu where you should choose Chrome launch.&lt;br&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%2Fh7ktdd4w89fr324g8d67.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%2Fh7ktdd4w89fr324g8d67.png" alt="Configuration context menu" width="800" height="407"&gt;&lt;/a&gt;&lt;br&gt;
And here we go! You will get the same config as in step #1 😎&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;2) After that, choose in the left top corner your option to launch the configuration inside the &lt;code&gt;Run and debug menu&lt;/code&gt; in VSCode&lt;br&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%2Foa1gi0obm8w3cnbtfzfr.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%2Foa1gi0obm8w3cnbtfzfr.png" alt="Debugging launch context menu" width="800" height="425"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;3) As a result, you will see the lifted application on a specified port!&lt;/p&gt;

&lt;p&gt;See you in the following article about controllers in a VSCode debugger 🥳&lt;/p&gt;

</description>
      <category>react</category>
      <category>debugging</category>
      <category>vscode</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Debugging Nodejs in VSCode</title>
      <dc:creator>Hleb Kryshyn</dc:creator>
      <pubDate>Tue, 03 May 2022 08:18:06 +0000</pubDate>
      <link>https://dev.to/dealwith/debugging-nodejs-in-vscode-14jk</link>
      <guid>https://dev.to/dealwith/debugging-nodejs-in-vscode-14jk</guid>
      <description>&lt;p&gt;👨‍💻 I want you to become a better software engineer through debugging in this series of articles.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Debugging is the process of detecting and removing existing and potential errors (also called 'bugs') in a software code that can cause it to behave unexpectedly or crash.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;⚙️ To configure debugging of Node in a VSCode, you should follow these steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Create a folder &lt;code&gt;.vscode&lt;/code&gt; at the root of your project.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Put a file &lt;code&gt;launch.json&lt;/code&gt; inside &lt;code&gt;.vscode&lt;/code&gt; folder. This file will be a config file for debugging.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Inside &lt;code&gt;launch.json&lt;/code&gt;, you should put this code&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ol&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;"configurations"&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;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Attach by Process ID"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"processId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"${command:PickProcess}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"request"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"attach"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"skipFiles"&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="s2"&gt;"&amp;lt;node_internals&amp;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;"type"&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"&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;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;blockquote&gt;
&lt;p&gt;💡 &lt;strong&gt;Tip:&lt;/strong&gt; You can generate the same code by pressing the "Add configuration" button in VSCode bottom right corner.&lt;br&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%2Fnn1gn9agjsejuer1hx54.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%2Fnn1gn9agjsejuer1hx54.png" alt="Add configuration green button" width="284" height="76"&gt;&lt;/a&gt;&lt;br&gt;
After clicking the button, you will see a context menu where you should choose Node.js Attach to process.&lt;br&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%2Feh1mywkuwjref2n8pblk.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%2Feh1mywkuwjref2n8pblk.png" alt="Configuration context menu" width="800" height="450"&gt;&lt;/a&gt;&lt;br&gt;
Node.js Attach to process will bring you the same configuration as in step #3&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;After that, go to the run and debug section in VSCode&lt;br&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%2F79v1ng8sbdnkkehee620.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%2F79v1ng8sbdnkkehee620.png" alt="Run and debug section in VSCode" width="94" height="96"&gt;&lt;/a&gt;&lt;br&gt;
Choose your configuration, and press start&lt;br&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%2F9v3la9ndzng9tfny35gh.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%2F9v3la9ndzng9tfny35gh.png" alt="Select and run configuration options" width="360" height="64"&gt;&lt;/a&gt;&lt;br&gt;
You should pick the node process you want to attach. Your running node application inside VSCode will be in the first place.&lt;br&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%2Ft0mo7wr51lpwpiebrdh9.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%2Ft0mo7wr51lpwpiebrdh9.png" alt="Context menu for choosing node process" width="800" height="290"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;But if you didn't find the right PID (process id) of your Node, I recommend you run a command that will show you the id of a running process on the exact localhost.&lt;/p&gt;

&lt;p&gt;For macOS&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;sudo &lt;/span&gt;lsof &lt;span class="nt"&gt;-i&lt;/span&gt; :PORT
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After getting the right PID, you should put it in a context menu, and here you go!&lt;/p&gt;

&lt;p&gt;See you in the following articles 🥳&lt;/p&gt;

</description>
      <category>node</category>
      <category>vscode</category>
      <category>debugging</category>
      <category>productivity</category>
    </item>
  </channel>
</rss>
