<?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: Dawid Sibiński</title>
    <description>The latest articles on DEV Community by Dawid Sibiński (@dsibinski).</description>
    <link>https://dev.to/dsibinski</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%2F378817%2F54e9c272-84a4-45eb-aa38-955d16959cd7.jpeg</url>
      <title>DEV Community: Dawid Sibiński</title>
      <link>https://dev.to/dsibinski</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/dsibinski"/>
    <language>en</language>
    <item>
      <title>5 Reasons To Not Use C# IDE For TypeScript Development</title>
      <dc:creator>Dawid Sibiński</dc:creator>
      <pubDate>Sun, 05 Nov 2023 09:40:15 +0000</pubDate>
      <link>https://dev.to/dsibinski/5-reasons-to-not-use-c-ide-for-typescript-development-3dcb</link>
      <guid>https://dev.to/dsibinski/5-reasons-to-not-use-c-ide-for-typescript-development-3dcb</guid>
      <description>&lt;p&gt;I know a few fellow devs who still use Visual Studio or Rider as their IDE for Typescript. If you’re one of them, this is going to be a little rant on you all 😄&lt;/p&gt;

&lt;p&gt;In this short article, I will give you 5 reasons why your backend code editor is not the best IDE for frontend development 😉&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Rider and Visual Studio are slow
&lt;/h2&gt;

&lt;p&gt;While I consider Rider much faster than Visual Studio, even the JetBrains editor is too heavy for TypeScript development. Both of these apps are not good candidates for an IDE for TypeScript. They were designed to work with complex, backend solutions. These IDEs include a lot of features by default that can’t be turned off, most of which are not needed when working with frontend code.&lt;/p&gt;

&lt;p&gt;This gets even worse if the solution you open contains both backend C# project and React app’s code, as it is in &lt;a href="https://learn.microsoft.com/en-us/visualstudio/javascript/tutorial-asp-net-core-with-react?view=vs-2022"&gt;Visual Studio’s .NET+React template&lt;/a&gt;. With time, even loading such a solution takes a lot of time. Especially if you use Visual Studio with &lt;a href="https://www.jetbrains.com/resharper"&gt;ReSharper&lt;/a&gt; 🙈&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Less IntelliSense and tooling support
&lt;/h2&gt;

&lt;p&gt;From my experience, Visual Studio doesn’t show as much &lt;a href="https://en.wikipedia.org/wiki/Intelligent_code_completion"&gt;IntelliSense info&lt;/a&gt; as, for instance, Visual Studio Code does. The navigation in TypeScript code doesn’t feel as smooth as it should.&lt;/p&gt;

&lt;p&gt;When I tried to use Rider or Visual Studio as IDE for TypeScript, I had issues working with popular frontend tooling like &lt;a href="https://prettier.io/"&gt;Prettier&lt;/a&gt; and &lt;a href="https://eslint.org/"&gt;ESLint&lt;/a&gt;. Theoretically, there are plugins for both of these IDEs, but in my experience they don’t always work properly. For instance, the “Format on save” feature of Prettier often doesn’t work in Rider for me. ESLint makes Visual Studio even slower (is that even possible?! 😅).&lt;/p&gt;

&lt;p&gt;It’s hard to fully explain if you only worked with TypeScript in Rider or Visual Studio, but I promise you that switching to VS Code makes a huge difference 🤪 Read on to get to know why!&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Confusion of concepts
&lt;/h2&gt;

&lt;p&gt;Let me explain my approach to frontend and backend first. To me, as a full stack developer, working on a frontend app requires a different mindset than working on backend. For instance, developing a React app requires me to think &lt;em&gt;The React Way&lt;/em&gt; (we discussed it already in an article about &lt;a href="https://dev.to/dsibinski/react-state-management-basics-3252"&gt;React state management&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;In my view, editing both frontend and backend code in the same editor makes you confuse concepts. If you learned JavaScript/TypeScript after working with C# for some time, you probably experienced trying to use &lt;code&gt;let&lt;/code&gt; in C# or declaring C# types with colon (&lt;code&gt;:&lt;/code&gt;) 😅 But this is only a tip of the iceberg.&lt;/p&gt;

&lt;p&gt;I think having a separate IDE for TypeScript makes you nicely switch context when working on the frontend app. Opening my TypeScript code editor, I immediately start &lt;em&gt;thinking in frontend&lt;/em&gt;. It instantly switches my approach to writing code. I somehow start to behave like a frontend developer, not a full stack one.&lt;/p&gt;

&lt;p&gt;I think such approach is beneficial. For instance, it lets me work on my frontend code as I would be a real consumer of the backend API, not the person who can implement the backend in whichever way I want. Thanks to that &lt;em&gt;switching of viewpoint&lt;/em&gt;, I can focus on designing my frontend code properly, without worrying about the backend.&lt;/p&gt;

&lt;p&gt;I also tend to make less assumptions like &lt;em&gt;oh no worries, I will do it on the server&lt;/em&gt;. At that moment, with my IDE for TypeScript open, I am a frontend developer. It often leads to better API design later on, because I don’t make any assumptions about the backend. Working on a frontend part of the app, I usually use API mocks first, knowing only the shape of data that should come from the API. Only later, when I’m done with the frontend part, I switch to Rider to actually implement the API.&lt;/p&gt;

&lt;p&gt;Of course, this can also work the other way around. You can first work on the backend, design your API according to the best practices (again – without even thinking about your frontend app) and finally switch to the frontend IDE, build the UI and consume the API instead of using mock in the first place.&lt;/p&gt;

&lt;p&gt;I hope you got what I mean here, but it’s not easy to clearly explain 🤪&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Temptation to sneak C# concepts to TS
&lt;/h2&gt;

&lt;p&gt;This point is a consequence of the previous one. If your IDE for TypeScript is the same as your C# code editor, you will be tempted to sneak C# concepts into TypeScript. I often see .NET developers entering TypeScript world using &lt;code&gt;var&lt;/code&gt; by default (which is kinda deprecated in JavaScript and considered a bad practice today) or enforcing C# brackets formatting style in their frontend code. I also noticed overuse of classes and inheritance in TypeScript, as well as confusing passing value/reference data directly into components instead of properly using &lt;a href="https://dev.to/dsibinski/react-state-management-basics-3252"&gt;&lt;code&gt;state&lt;/code&gt; and &lt;code&gt;props&lt;/code&gt; in React&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;To sum it up: isolating yourself as a frontend developer by using a TypeScript-specific IDE (like VS Code) will help you learn good frontend practices quicker 🙂&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Because VS Code is better 😀
&lt;/h2&gt;

&lt;p&gt;Last, but not least: the main reason to not use &lt;a href="https://visualstudio.microsoft.com/"&gt;Visual Studio&lt;/a&gt; or &lt;a href="https://www.jetbrains.com/rider/"&gt;Rider&lt;/a&gt; for TypeScript development is simple: &lt;strong&gt;&lt;a href="https://code.visualstudio.com/"&gt;Visual Studio Code&lt;/a&gt; is better!&lt;/strong&gt;😀&lt;/p&gt;

&lt;p&gt;VS Code is industry standard for frontend development today. According to &lt;a href="https://survey.stackoverflow.co/2023/#section-most-popular-technologies-integrated-development-environment"&gt;Stack Overflow Developer Survey 2023&lt;/a&gt;, over 70% of all developers use Visual Studio Code:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--eoKWGPKU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i0.wp.com/www.codejourney.net/wp-content/uploads/2023/11/stack-overflow-survey-2023-vs-code.png%3Fresize%3D928%252C340%26ssl%3D1" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--eoKWGPKU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i0.wp.com/www.codejourney.net/wp-content/uploads/2023/11/stack-overflow-survey-2023-vs-code.png%3Fresize%3D928%252C340%26ssl%3D1" alt="Visual Studio Code is the most widely used IDE for TypeScript (and IDE in general)" width="800" height="293"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;VS Code is lightweight. It doesn’t have all heavy features included by default. If you want something additional, it must be installed as an extension. By the way, the extensions are really great and actively developed by the community.&lt;/p&gt;

&lt;p&gt;VS Code is mostly written in TypeScript, which makes is somewhat designed for TypeScript. It has great search features, awesome IntelliSense for TypeScript and works really fast. Especially compared to Visual Studio or even Rider.&lt;/p&gt;

&lt;p&gt;Visual Studio Code can also be run on any platform. It even has a &lt;a href="https://vscode.dev/"&gt;fully-featured web version&lt;/a&gt;. The IDE is also completely free and open-source.&lt;/p&gt;

&lt;p&gt;I think I won’t continue listing numerous advantages of VS Code here. If you’re reading this, and you are still not encouraged to switch to VS Code for TypeScript development, please give it a try 🙂 Or another try if you already tried, but it didn’t click. This time, first &lt;a href="https://www.youtube.com/playlist?list=PLj6YeMhvp2S5UgiQnBfvD7XgOMKs3O_G6"&gt;watch some introductory videos&lt;/a&gt; with tips on how to get started and get the most of the editor. You can also check the &lt;a href="https://dev.to/dsibinski/10-vs-code-extensions-i-couldnt-live-without-4npa"&gt;VS Code extensions I use on a daily basis&lt;/a&gt; to make your work with this editor easier.&lt;/p&gt;

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

&lt;p&gt;That’s it! I really wanted to write this article one day. Do you know that feeling when you learned something new or made significant progress in some area of your life, and you see people still struggling with what you have overcome? It’s this moment when you would really love to give these people all of your knowledge and make them magically change their lives – the same way you did 😀 I feel exactly that when I see fellow developers struggling (it’s a matter of opinion, I know 😀) with Typescript in Visual Studio 🙈&lt;/p&gt;

&lt;p&gt;I know I can’t change you and your beliefs and I don’t want to do that. But the great thing is that I can share my point of view and try to encourage you to alter yours a little. At least try and let me know what are your thoughts on that 😉&lt;/p&gt;

&lt;p&gt;Also, if you’re a frontend or full stack developer working in a backend IDE like Rider or Visual Studio, let me know why! I’m really curious. Did you try VS Code? If yes, what didn’t fit?&lt;/p&gt;

&lt;p&gt;The post &lt;a href="https://www.codejourney.net/5-reasons-to-not-use-c-ide-for-typescript-development/"&gt;5 Reasons To Not Use C# IDE For TypeScript Development&lt;/a&gt; appeared first on &lt;a href="https://www.codejourney.net"&gt;CodeJourney.net&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>csharp</category>
      <category>rider</category>
      <category>roadtodotnetfullstac</category>
    </item>
    <item>
      <title>React State Management Basics</title>
      <dc:creator>Dawid Sibiński</dc:creator>
      <pubDate>Sun, 29 Oct 2023 06:49:10 +0000</pubDate>
      <link>https://dev.to/dsibinski/react-state-management-basics-3252</link>
      <guid>https://dev.to/dsibinski/react-state-management-basics-3252</guid>
      <description>&lt;p&gt;If I were to point out a single concept that is critical to understand in React development, it would be state management.&lt;/p&gt;

&lt;p&gt;So what is React state management? How is it different from managing data in C# or Java? Let’s find out! 🙂&lt;/p&gt;

&lt;h2&gt;
  
  
  State
&lt;/h2&gt;

&lt;p&gt;If you are a backend or desktop developer, you may have never come across the term of state. At least, I never used it before learning frontend web development. Surely not in the context it is used in frameworks like React. The term more familiar to me at that time was &lt;em&gt;data binding&lt;/em&gt; known from &lt;a href="https://learn.microsoft.com/en-us/dotnet/desktop/wpf/overview" rel="noopener noreferrer"&gt;WPF&lt;/a&gt; or &lt;a href="https://learn.microsoft.com/en-us/dotnet/desktop/winforms/overview" rel="noopener noreferrer"&gt;WinForms&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This is what &lt;a href="https://learn.microsoft.com/en-us/dotnet/desktop/wpf/data" rel="noopener noreferrer"&gt;WPF documentation&lt;/a&gt; says:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;cite&gt;Data binding is the process that establishes a connection between the app UI and the data it displays. If the binding has the correct settings and the data provides the proper notifications, when the data changes its value, the elements that are bound to the data reflect changes automatically&lt;/cite&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In case of WPF, the crucial part to me is  &lt;strong&gt;If the binding has the correct settings and the data provides the proper notifications&lt;/strong&gt;  &lt;strong&gt;(…)&lt;/strong&gt;. If you have ever worked with WPF, you know how frustrating can these &lt;em&gt;notifications&lt;/em&gt; be (any &lt;code&gt;INotifyPropertyChanged&lt;/code&gt; fans here?).&lt;/p&gt;

&lt;p&gt;WPF’s state management it not that bad. However, React has something better 😉&lt;/p&gt;

&lt;p&gt;React introduces us to a concept of &lt;em&gt;state&lt;/em&gt;. In React components, you do not set anything directly, like calling some code to update an input’s value (this is possible, we’re still in &lt;a href="https://www.codejourney.net/10-most-shocking-javascript-features-for-csharp-developers/" rel="noopener noreferrer"&gt;JavaScript world&lt;/a&gt;, but it’s not a &lt;em&gt;React way&lt;/em&gt; of doing stuff). You don’t directly bind your UI controls with data like you would in WPF or WinForms. Instead, you keep the data in memory, which is a current &lt;em&gt;state&lt;/em&gt; of the UI (the whole app or a piece of it).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;When the state changes, your UI is updated by React&lt;/strong&gt;. In other words – &lt;strong&gt;in React, UI is a function of state&lt;/strong&gt; :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;UI = fn(state)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It means that your React app (or its individual pieces called &lt;em&gt;components&lt;/em&gt;) take some state and output the actual, rendered UI.&lt;/p&gt;

&lt;p&gt;This is React state management in a nutshell. Let’s explore it a bit more 😉&lt;/p&gt;

&lt;p&gt;_Small disclaimer: _I will focus on state in React functional componets. I consider &lt;a href="https://react.dev/reference/react/Component" rel="noopener noreferrer"&gt;class components somewhat legacy&lt;/a&gt;. I think this meme summarizes it best 😀:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.freecodecamp.org/news/functional-setstate-is-the-future-of-react-374f30401b6b/" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi0.wp.com%2Fwww.codejourney.net%2Fwp-content%2Fuploads%2F2023%2F10%2Freact-setstate-meme.jpg%3Fresize%3D500%252C381%26ssl%3D1" alt="setState meme"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  The Naive Way
&lt;/h3&gt;

&lt;p&gt;Let’s try to approach React state management as C# developer. In React, the basic piece of UI we create is a component. Let’s add one:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Button&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-bootstrap/Button&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;NaiveComponent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;I am a naive component&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Button&lt;/span&gt; &lt;span class="na"&gt;variant&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"success"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Click me!&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&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;For now, we render some text and a button which does nothing. What we want is to have some data displayed, like a number, which is incremented on every button click. Let’s try to implement that naively:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;NaiveComponent&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;let&lt;/span&gt; &lt;span class="nx"&gt;myCount&lt;/span&gt; &lt;span class="o"&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;&amp;lt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;I am a naive component&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Current count: &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;myCount&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Button&lt;/span&gt;
        &lt;span class="na"&gt;variant&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"success"&lt;/span&gt;
        &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="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;myCount&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="si"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        Click me!
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&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;Now, let’s check if it works:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi0.wp.com%2Fwww.codejourney.net%2Fwp-content%2Fuploads%2F2023%2F10%2Fchrome_wkZlXfCKTf.gif%3Fresize%3D536%252C285%26ssl%3D1" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi0.wp.com%2Fwww.codejourney.net%2Fwp-content%2Fuploads%2F2023%2F10%2Fchrome_wkZlXfCKTf.gif%3Fresize%3D536%252C285%26ssl%3D1" alt="Naive component - not working"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It looks nothing happens 🥹 To investigate that, we can add a &lt;code&gt;console.log&lt;/code&gt; (the most common debugging technique in JavaScript world 😅) to the &lt;code&gt;onClick&lt;/code&gt; event:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nx"&gt;myCount&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
          &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;myCount&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;How does that look in the console now?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi0.wp.com%2Fwww.codejourney.net%2Fwp-content%2Fuploads%2F2023%2F10%2Fchrome_g62ao8n7FW.gif%3Fresize%3D1071%252C591%26ssl%3D1" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi0.wp.com%2Fwww.codejourney.net%2Fwp-content%2Fuploads%2F2023%2F10%2Fchrome_g62ao8n7FW.gif%3Fresize%3D1071%252C591%26ssl%3D1" alt="React state management - naive way (like C# dev), not working"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Woooow, something is really going wrong here! The data is updated in memory, but not reflected in the UI 🤔&lt;/p&gt;

&lt;p&gt;Why does that happen? Because &lt;code&gt;myCount&lt;/code&gt; is not a state. It’s just some variable we created hoping that it will work fine as part of the UI. Remember what we have discussed in the previous section – we need to start &lt;em&gt;thinking in React&lt;/em&gt;. This is &lt;em&gt;The&lt;/em&gt; &lt;em&gt;React way&lt;/em&gt;, not &lt;em&gt;Java way&lt;/em&gt; or &lt;em&gt;C# way&lt;/em&gt; anymore.&lt;/p&gt;

&lt;h3&gt;
  
  
  The React Way
&lt;/h3&gt;

&lt;p&gt;So, how to use React state management properly in our example? We need to make &lt;code&gt;myCount&lt;/code&gt; be a part of component’s state. The simplest way to do that looks as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;TheReactWayComponent&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;myCount&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setMyCount&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;I am a React Way component&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Current count: &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;myCount&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Button&lt;/span&gt;
        &lt;span class="na"&gt;variant&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"success"&lt;/span&gt;
        &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="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;setMyCount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;myCount&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        Click me!
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&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;First, instead of declaring a “normal” variable for storing our UI-related data, we used the &lt;code&gt;useState&lt;/code&gt; &lt;a href="https://react.dev/reference/react#state-hooks" rel="noopener noreferrer"&gt;hook&lt;/a&gt;. As you can see, it returns an array with two things: our state variable (&lt;code&gt;myCount)&lt;/code&gt;and a function to update its value&lt;code&gt;&lt;/code&gt;(&lt;code&gt;setMyCount&lt;/code&gt;). We also set the initial value to &lt;code&gt;0&lt;/code&gt;. A good practice is to always use a construct like &lt;code&gt;[myCount, setMyCount]&lt;/code&gt; to destructure what &lt;code&gt;useState&lt;/code&gt; returns into named, separate objects.&lt;/p&gt;

&lt;p&gt;Now we are managing our component’s state &lt;em&gt;The React Way&lt;/em&gt;. Does it work? Let’s see:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi0.wp.com%2Fwww.codejourney.net%2Fwp-content%2Fuploads%2F2023%2F10%2Fchrome_OJMhjuDMmd.gif%3Fresize%3D464%252C215%26ssl%3D1" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi0.wp.com%2Fwww.codejourney.net%2Fwp-content%2Fuploads%2F2023%2F10%2Fchrome_OJMhjuDMmd.gif%3Fresize%3D464%252C215%26ssl%3D1" alt="React state management - The React Way"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Great! We have just learned how the basic form of state management works in React. That was easy, wasn’t it? 😉&lt;/p&gt;

&lt;p&gt;Now, let us discuss one more aspect related to the state itself.&lt;/p&gt;

&lt;h3&gt;
  
  
  Reference vs value
&lt;/h3&gt;

&lt;p&gt;We know the React Way for state management now. We feel confident. However, we are also used to how data is managed in C# or Java, especially in terms of &lt;a href="https://dev.to/dsibinski/net-internals-02-stack-and-heap-net-data-structures-4i7p-temp-slug-7161613"&gt;handling reference and value types&lt;/a&gt;. This knowledge will come very handy now 🙂&lt;/p&gt;

&lt;p&gt;Let’s try to create a bit more complex component:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Person&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;id&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="nl"&gt;name&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="nl"&gt;age&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="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;ObjectHolderComponent&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="na"&gt;johnInitialValue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Person&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;id&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="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;John Doe&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;30&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;john&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setJohn&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Person&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;johnInitialValue&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;ID: &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;john&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Name: &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;john&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Age: &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;john&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;age&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Button&lt;/span&gt;
        &lt;span class="na"&gt;variant&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"success"&lt;/span&gt;
        &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="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;currentJohnObject&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;john&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
          &lt;span class="nx"&gt;currentJohnObject&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;age&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;currentJohnObject&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;age&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
          &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;currentJohnObject&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
          &lt;span class="nf"&gt;setJohn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;currentJohnObject&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        Make John older
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&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;Now, instead of storing a single value in our component’s state, we store a whole object of type &lt;code&gt;Person&lt;/code&gt;. The object has a few properties: &lt;code&gt;id&lt;/code&gt;, &lt;code&gt;name&lt;/code&gt; and &lt;code&gt;age&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;There is also a button. We want this button to take the current &lt;code&gt;john&lt;/code&gt; object, increment the value of &lt;code&gt;age&lt;/code&gt; on it and update the state. We do it The React Way using &lt;code&gt;setJohn&lt;/code&gt; function returned by &lt;code&gt;useState&lt;/code&gt;. Just to be sure, we also have the &lt;code&gt;console.log(john)&lt;/code&gt; just before updating the state. Does that work as we expected?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi0.wp.com%2Fwww.codejourney.net%2Fwp-content%2Fuploads%2F2023%2F10%2Fchrome_hlgFthtHBT.gif%3Fresize%3D873%252C656%26ssl%3D1" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi0.wp.com%2Fwww.codejourney.net%2Fwp-content%2Fuploads%2F2023%2F10%2Fchrome_hlgFthtHBT.gif%3Fresize%3D873%252C656%26ssl%3D1" alt="Changing an object's (reference) internal variable does not trigger a re-render, even we use useState"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Eh, what’s happening here this time? We can clearly see that &lt;code&gt;age&lt;/code&gt; is updated on the object on each click, but why isn’t the UI re-rendered? 🤔&lt;/p&gt;

&lt;p&gt;As I mentioned before, it’s critical to understand the difference between reference and value types here. If you don’t know it, &lt;a href="https://dev.to/dsibinski/net-internals-02-stack-and-heap-net-data-structures-4i7p-temp-slug-7161613"&gt;go and make up for it now&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The reason it does not work is that we haven’t updated the actual content of &lt;code&gt;john&lt;/code&gt; state variable by calling &lt;code&gt;setJohn(currentJohnObject)&lt;/code&gt;. &lt;strong&gt;What is really being hold in &lt;code&gt;john&lt;/code&gt; variable is the reference (pointer, address in memory) to the actual object&lt;/strong&gt;. And this is what React tracks. We didn’t really update it, because we assigned the same instance of the object to the state. It doesn’t matter that we updated its internal property &lt;code&gt;age&lt;/code&gt; – the reference itself wasn’t updated.&lt;/p&gt;

&lt;p&gt;How do we solve that? Well, in current solution we’d need to create a copy of &lt;code&gt;john&lt;/code&gt; object before using &lt;code&gt;setJohn&lt;/code&gt; to alter the state. In effect, we’ll get a new instance of the object in memory and &lt;code&gt;john&lt;/code&gt; variable will hold a new reference (address) to it.&lt;/p&gt;

&lt;p&gt;So, if we only change our &lt;code&gt;onClick&lt;/code&gt; implementation to this one:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;johnCopy&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;john&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
          &lt;span class="nx"&gt;johnCopy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;age&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;john&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;age&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
          &lt;span class="nf"&gt;setJohn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;johnCopy&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;Everything starts to work as expected:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi0.wp.com%2Fwww.codejourney.net%2Fwp-content%2Fuploads%2F2023%2F10%2Fchrome_yfmHz6z0Xn.gif%3Fresize%3D333%252C236%26ssl%3D1" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi0.wp.com%2Fwww.codejourney.net%2Fwp-content%2Fuploads%2F2023%2F10%2Fchrome_yfmHz6z0Xn.gif%3Fresize%3D333%252C236%26ssl%3D1" alt="Changing a reference state by creating a copy of it works fine in React"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I think you now understand how React state management works. I also hope that you see the issues managing state in such a way can bring. Even in this trivial example, we create a new instance of an object on every button click. Apart from memory usage considerations, this just looks ugly. Imagine manually creating copies of much more complex objects, like classes storing arrays or dictionaries. This gets pretty wild 🤪&lt;/p&gt;

&lt;p&gt;We will see how this issue can be addressed by the end of this article. But first, let’s discuss &lt;code&gt;props&lt;/code&gt; – another concept critical to really understand React state management.&lt;/p&gt;

&lt;h2&gt;
  
  
  Props
&lt;/h2&gt;

&lt;p&gt;Apart from &lt;code&gt;state&lt;/code&gt;, we also use &lt;code&gt;props&lt;/code&gt; to control the state of our React components. The name is a short for &lt;em&gt;properties&lt;/em&gt;, which quite well describes its purpose. &lt;code&gt;Props&lt;/code&gt; are the data input provided to a component from outside (from a parent component). They are immutable and cannot be changed inside the component which receives them. Let’s see some examples.&lt;/p&gt;

&lt;h3&gt;
  
  
  Sharing state between components
&lt;/h3&gt;

&lt;p&gt;The most common usage for &lt;code&gt;props&lt;/code&gt; is sharing state between components. Imagine that you have an input, where the user manually enters some data. You want to use the current value of this input in two other components. This is where you need to share your component’s state (the value of the input) with these two other components. We often call it &lt;em&gt;lifting the state up&lt;/em&gt; – you keep your state higher in the components tree, so the child components can use it.&lt;/p&gt;

&lt;p&gt;Let’s try to see an example of connecting &lt;code&gt;state&lt;/code&gt; with &lt;code&gt;props&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;PersonData&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;minimumAge&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;5&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;maximumAge&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;100&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;age&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setAge&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;number&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;minimumAge&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;handleAgeChange&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;event&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ChangeEvent&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;HTMLInputElement&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;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;enteredAge&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;parseInt&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="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;enteredAge&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="nx"&gt;minimumAge&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;enteredAge&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="nx"&gt;maximumAge&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;setAge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;enteredAge&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="p"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Form&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Group&lt;/span&gt; &lt;span class="na"&gt;controlId&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"age"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Label&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Your age&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Label&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Control&lt;/span&gt;
            &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"number"&lt;/span&gt;
            &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;age&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
            &lt;span class="na"&gt;onChange&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;handleAgeChange&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
            &lt;span class="na"&gt;min&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;minimumAge&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
            &lt;span class="na"&gt;max&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;maximumAge&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
          &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Group&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Form&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;DaysLiving&lt;/span&gt; &lt;span class="na"&gt;currentAge&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;age&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;YearsUntilCentenarian&lt;/span&gt; &lt;span class="na"&gt;currentAge&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;age&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&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;As you can see, at lines 4 and 9 we manage the state variable &lt;code&gt;age&lt;/code&gt;. This is the old stuff we have already seen.&lt;/p&gt;

&lt;p&gt;However, at lines 27 and 28 we are passing the &lt;code&gt;age&lt;/code&gt; state variable into &lt;code&gt;DaysLiving&lt;/code&gt; and &lt;code&gt;YearsUntilCentenarian&lt;/code&gt; children components as &lt;code&gt;currentAge&lt;/code&gt; prop. This is how the &lt;code&gt;DaysLiving&lt;/code&gt; component is implemented:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;DaysLivingProps&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;currentAge&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="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;DaysLiving&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;DaysLivingProps&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;daysLived&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;currentAge&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;365&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;You have lived for &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;daysLived&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; days.&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice that &lt;code&gt;props&lt;/code&gt; is simply a typed object you pass to a function component. To make things easier, you can also use object destructuring and accept the props in the following way:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;DaysLiving&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="nx"&gt;currentAge&lt;/span&gt;&lt;span class="p"&gt;}:&lt;/span&gt; &lt;span class="nx"&gt;DaysLivingProps&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;daysLived&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;currentAge&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;365&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="c1"&gt;/// ... rest of the code&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That way, you don’t need to write &lt;code&gt;props.currentAge&lt;/code&gt; every time you want to use this property inside the component.&lt;/p&gt;

&lt;h3&gt;
  
  
  Does changing props always trigger a re-render?
&lt;/h3&gt;

&lt;p&gt;Well, generally the answer to this question is &lt;em&gt;yes&lt;/em&gt;. Every time a prop of a component changes, this component will get re-rendered. However, this is not &lt;em&gt;entirely&lt;/em&gt; true 🤪&lt;/p&gt;

&lt;p&gt;To make this belief true, we need to assume that this prop is changed &lt;em&gt;in a React way&lt;/em&gt;. So, to take things literally, consider this component we saw before:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;DaysLiving&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="nx"&gt;currentAge&lt;/span&gt;&lt;span class="p"&gt;}:&lt;/span&gt; &lt;span class="nx"&gt;DaysLivingProps&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;daysLived&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;currentAge&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;365&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;You have lived for &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;daysLived&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; days.&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;From its perspective only, it accepts a &lt;code&gt;currentAge&lt;/code&gt; property. For this component to re-render, it’s not enough that the &lt;code&gt;currentAge&lt;/code&gt; property changes in any way. &lt;strong&gt;Its value must be changed by mutating the state in the parent component&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;So, if the value provided as &lt;code&gt;currentAge&lt;/code&gt; to &lt;code&gt;DaysLiving&lt;/code&gt; component changes in the parent component by properly mutating the state (with &lt;code&gt;setAge&lt;/code&gt; mutation callback, in our case):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;PersonData&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="c1"&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;age&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setAge&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;number&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;minimumAge&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;handleAgeChange&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;event&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ChangeEvent&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;HTMLInputElement&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// ...&lt;/span&gt;
      &lt;span class="nf"&gt;setAge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;enteredAge&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="p"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
      // ...
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;DaysLiving&lt;/span&gt; &lt;span class="na"&gt;currentAge&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;age&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
      // ...
    &lt;span class="p"&gt;&amp;lt;/&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;the child component (&lt;code&gt;DaysLiving&lt;/code&gt;) will get re-rendered.&lt;/p&gt;

&lt;p&gt;This is because when a parent component changes, React by default re-renders the parent component itself and all of its children.&lt;/p&gt;

&lt;p&gt;If you modified the &lt;code&gt;age&lt;/code&gt; variable in the parent compont directly, without using &lt;code&gt;setAge&lt;/code&gt; (which we already know it’s incorrect), the &lt;code&gt;currentAge&lt;/code&gt; prop would technically change, but the &lt;code&gt;DaysLiving&lt;/code&gt; component will not get re-rendered.&lt;/p&gt;

&lt;h3&gt;
  
  
  state vs props
&lt;/h3&gt;

&lt;p&gt;This is a question that people oftern ask: what’s the difference between &lt;code&gt;props&lt;/code&gt; and &lt;code&gt;state&lt;/code&gt; in React? 🤔&lt;/p&gt;

&lt;p&gt;I would start with addressing this differently: what do &lt;code&gt;props&lt;/code&gt; and &lt;code&gt;state&lt;/code&gt; have in common?&lt;/p&gt;

&lt;p&gt;As you already know, both are used for React state management. Both of them influence when the components will be re-rendered by React. Props and state are the absolute foundations of React.&lt;/p&gt;

&lt;p&gt;The main difference is that &lt;code&gt;state&lt;/code&gt; is used internally in a component, while &lt;code&gt;props&lt;/code&gt; are used to pass information from parent to children components. &lt;code&gt;State&lt;/code&gt; is also naturally mutable within a component where it’s defined, but &lt;code&gt;props&lt;/code&gt; are immutable and cannot be changed in a component that receives and uses them.&lt;/p&gt;

&lt;h2&gt;
  
  
  React state management libraries
&lt;/h2&gt;

&lt;p&gt;That’s basically everything you need to know to be able to comfortably work with React state management. However, I mentioned before that managing state using only built-in React mechanisms actually sucks 🤪 That’s why I’d like to make a short point on state management libraries.&lt;/p&gt;

&lt;p&gt;Maybe you heard about &lt;a href="https://redux.js.org/" rel="noopener noreferrer"&gt;Redux&lt;/a&gt;, &lt;a href="https://github.com/pmndrs/zustand" rel="noopener noreferrer"&gt;Zustand&lt;/a&gt; or &lt;a href="https://mobx.js.org/README.html" rel="noopener noreferrer"&gt;MobX&lt;/a&gt;. All of them are state management libraires for React. But why would you even need one? And should you learn one now?&lt;/p&gt;

&lt;p&gt;In my opinion, you can easily start working with React using the built-in state management mechanisms we discussed today. It’s good to know how it works in practice. However, the truth is that as your application grows and you want to keep it scalable and maintenable, you will need a state management library at some point. As soon as your components tree gets bigger, sharing data and state will not be as easy as “passing props to a children component”. You will need to share state between multiple components in the tree, sometimes not only between parent and children, but also with another components defined on the same level or even in a totally different place of the tree.&lt;/p&gt;

&lt;p&gt;This is where React state management libraries come very handy. They solve many of the React’s issues that come to the surface as your state gets complex. But even if you use one, you will still always need &lt;code&gt;state&lt;/code&gt; and &lt;code&gt;props&lt;/code&gt;. That’s why it’s critical to understand these two basic concepts first and play with them for some time.&lt;/p&gt;

&lt;p&gt;If you’re starting out, it’s good to know that state management libraries exist and that one day you will have to get your hands on one (or more 😉) of them. I hope to share my thoughts on state management libraries in a separate article one day.&lt;/p&gt;

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

&lt;p&gt;That’s it! Now you should know how React manages state of its components. Of course, we didn’t cover everything related to state management in React, but I hope you got the basics 😉&lt;/p&gt;

&lt;p&gt;You can find all of the source code used in this article &lt;a href="https://github.com/dsibinski/codejourney/tree/main/react-state-management" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How do you manage state in your React apps? Do you use a state management library? If yes, which one and why? Let me know in the comments below!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The post &lt;a href="https://www.codejourney.net/react-state-management-basics/" rel="noopener noreferrer"&gt;React State Management Basics&lt;/a&gt; appeared first on &lt;a href="https://www.codejourney.net" rel="noopener noreferrer"&gt;CodeJourney.net&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>javascript</category>
      <category>react</category>
      <category>roadtodotnetfullstac</category>
    </item>
    <item>
      <title>TypeScript Compiler Explained</title>
      <dc:creator>Dawid Sibiński</dc:creator>
      <pubDate>Tue, 17 Oct 2023 04:08:05 +0000</pubDate>
      <link>https://dev.to/dsibinski/typescript-compiler-explained-10id</link>
      <guid>https://dev.to/dsibinski/typescript-compiler-explained-10id</guid>
      <description>&lt;p&gt;As a frontend developer, one of the things you should know is how TypeScript compiler works. Sooner or later you will work with this language (which I sincerely wish you!), so it’s good to know your stuff 😉&lt;/p&gt;

&lt;p&gt;In this article, I will explain TypeScript compiler to you in simple terms. We will avoid complex stuff – only what you need for your everyday frontend developer’s work 🙂&lt;/p&gt;

&lt;h2&gt;
  
  
  Few basic facts about TypeScript
&lt;/h2&gt;

&lt;p&gt;For starters, let’s establish some quick facts about TypeScript as a language.&lt;/p&gt;

&lt;h3&gt;
  
  
  TypeScript is a superset of JavaScript
&lt;/h3&gt;

&lt;p&gt;You may have heard that TypeScript is a superset of JavaScript. In other words, every JavaScript code is a valid TypeScript code. In case of TypeScript, being a “superset” means adding types information on top of perfectly legit JavaScript code.&lt;/p&gt;

&lt;p&gt;Why is TypeScript only adding its types on top of JavaScript? In order to be able to remove them easily 🙂 But why would it do that?!&lt;/p&gt;

&lt;h3&gt;
  
  
  Browser doesn’t understand TypeScript
&lt;/h3&gt;

&lt;p&gt;The answer is that TypeScript cannot be run directly by a web browser (or NodeJS).&lt;/p&gt;

&lt;p&gt;Let’s take this trivial TypeScript code:&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;let&lt;/span&gt; &lt;span class="nx"&gt;age&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;27&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and try to paste it into Google Chrome’s console in order to execute it:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--qUoQJ7xC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i0.wp.com/www.codejourney.net/wp-content/uploads/2023/10/TypeScript-in-chrome-console.png%3Fresize%3D438%252C145%26ssl%3D1" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--qUoQJ7xC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i0.wp.com/www.codejourney.net/wp-content/uploads/2023/10/TypeScript-in-chrome-console.png%3Fresize%3D438%252C145%26ssl%3D1" alt="TypeScript code cannot be understood by a web browser" width="438" height="145"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you can see, it fails. The &lt;code&gt;number&lt;/code&gt; type annotation is unknown to the browser. It means that &lt;strong&gt;before any TypeScript code is run in the browser, the information about types must be stripped out&lt;/strong&gt;. In the end, browsers and NodeJS environments can only execute JavaScript. This is in short what TypeScript compiler does, and we’ll get into the details soon. For now, this leads us to another conclusion, that…&lt;/p&gt;

&lt;h3&gt;
  
  
  TypeScript is for developers
&lt;/h3&gt;

&lt;p&gt;As we have just discovered, types must be removed by the TypeScript compiler before the code can be executed by the browser. In fact, this line of TypeScript:&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;let&lt;/span&gt; &lt;span class="nx"&gt;age&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;27&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;produces the following JavaScript output when processed by the TypeScript compiler:&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;var&lt;/span&gt; &lt;span class="nx"&gt;age&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;27&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 effectively the same code we wrote in TypeScript, but without type annotations.&lt;/p&gt;

&lt;p&gt;Wrong data types assignments will only be detected at compile time:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Rjqf0xXy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i0.wp.com/www.codejourney.net/wp-content/uploads/2023/10/tsc-compilation-error.png%3Fresize%3D576%252C241%26ssl%3D1" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Rjqf0xXy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i0.wp.com/www.codejourney.net/wp-content/uploads/2023/10/tsc-compilation-error.png%3Fresize%3D576%252C241%26ssl%3D1" alt="tsc compilation error about wrong type" width="576" height="241"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;but as soon as it’s compiled, this protection is not there anymore 🤷‍♂️&lt;/p&gt;

&lt;p&gt;This discovery means that &lt;strong&gt;TypeScript is for developers&lt;/strong&gt;. Its job is to make our lives easier, Of course, in the end it also improves the end users’ experience, because &lt;a href="https://www.codejourney.net/is-it-worth-migrating-to-typescript/"&gt;programming in TypeScript is much better than using pure JS&lt;/a&gt;. But you can already see that TypeScript it not present at runtime at all. It only protects us until the compilation step by static types checking.&lt;/p&gt;

&lt;p&gt;The philosophy is more or less as follows 😀:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://anjulashanaka.medium.com/say-goodbye-to-runtime-errors-with-typescript-7afbae84e75f"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--MfiDpISI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i0.wp.com/www.codejourney.net/wp-content/uploads/2023/10/typescript-no-runtime-errors-if-code-does-not-compile-meme.jpg%3Fresize%3D602%252C333%26ssl%3D1" alt="TypeScript compiler only protects you at runtime (during compilation)" width="602" height="333"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;What’s worth mentioning, as the &lt;a href="https://www.typescriptlang.org/docs/handbook/typescript-from-scratch.html"&gt;language’s specification&lt;/a&gt; says, “TypeScript never changes the runtime behavior of JavaScript code”.&lt;/p&gt;

&lt;h2&gt;
  
  
  TypeScript compiler in practice
&lt;/h2&gt;

&lt;h3&gt;
  
  
  tsc
&lt;/h3&gt;

&lt;p&gt;TypeScript compiler is actually a CLI tool called &lt;code&gt;tsc&lt;/code&gt;. It can be installed globally on your machine and used directly or built into your IDE. Refer to &lt;a href="https://www.typescriptlang.org/download"&gt;official documentation&lt;/a&gt; for installation details.&lt;/p&gt;

&lt;p&gt;The compiler can also be installed locally in your project. It can then be set up as part of the build pipeline, which is supported by many &lt;a href="https://dev.to/dsibinski/what-is-a-javascript-bundler-429o"&gt;bundlers&lt;/a&gt;. That’s why, when working on a TypeScript project, you may never encounter any direct usages of the &lt;code&gt;tsc&lt;/code&gt; command.&lt;/p&gt;

&lt;h3&gt;
  
  
  tsconfig.json
&lt;/h3&gt;

&lt;p&gt;In order to make working with TypeScript compiler easier, you should use a &lt;code&gt;tsconfig.json&lt;/code&gt; file. It’s a JSON file containing all compilation settings. This is quite important, because, in opposite to C# or Java compilers, the TypeScript’s one allows for quite extensive (and flexible) configuration.&lt;/p&gt;

&lt;p&gt;When you use the &lt;code&gt;tsc&lt;/code&gt; command, it looks for &lt;code&gt;tsconfig.file&lt;/code&gt; in the current directory or any of the parent directories until it finds one. You can also provide a custom &lt;code&gt;tsconfig.json&lt;/code&gt; location via &lt;code&gt;--project&lt;/code&gt; parameter.&lt;/p&gt;

&lt;p&gt;The simplest &lt;code&gt;tsconfig.json&lt;/code&gt; file you get after initializing a new TypeScript project with &lt;code&gt;tsc --init&lt;/code&gt; looks as follows:&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;"compilerOptions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"target"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"es2016"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"module"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"commonjs"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"forceConsistentCasingInFileNames"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"strict"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"skipLibCheck"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;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;p&gt;We will not explore all the individual settings in this article. The &lt;a href="https://www.typescriptlang.org/docs/handbook/compiler-options.html"&gt;official documentation does a great job&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  TypeScript compiler – example
&lt;/h3&gt;

&lt;p&gt;Let’s now see how it works.&lt;/p&gt;

&lt;p&gt;Having a bit more complex TypeScript file as an example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// test.ts&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;Person&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;name&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="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;age&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="kd"&gt;constructor&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="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;age&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="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;name&lt;/span&gt; &lt;span class="o"&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;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;age&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;age&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="nx"&gt;getName&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="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;name&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="nx"&gt;getAge&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="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;age&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;person&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Person&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;John&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;27&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;person&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getName&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt; &lt;span class="c1"&gt;// Output: John&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;person&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getAge&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt; &lt;span class="c1"&gt;// Output: 27&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice the &lt;code&gt;.ts&lt;/code&gt; extension. This tells the compiler that this file contains TypeScript code.&lt;/p&gt;

&lt;p&gt;Having &lt;code&gt;tsc&lt;/code&gt; installed globally, we can compile it by executing the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;tsc test.ts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For the file given above, the output of this command is the following JavaScript file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// test.js&lt;/span&gt;
&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;Person&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="cm"&gt;/** @class */&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&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="nx"&gt;Person&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;age&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;name&lt;/span&gt; &lt;span class="o"&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;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;age&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;age&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="nx"&gt;Person&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;prototype&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="nx"&gt;Person&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;prototype&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getAge&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;age&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;Person&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;})();&lt;/span&gt;
&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;person&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Person&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;John&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;27&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;person&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getName&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt; &lt;span class="c1"&gt;// Output: John&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;person&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getAge&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt; &lt;span class="c1"&gt;// Output: 27&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Few things to note:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;there is no information about types in the &lt;code&gt;.js&lt;/code&gt; file. As we discussed before, this is intentional – only pure JavaScript code can be understood by the browser&lt;/li&gt;
&lt;li&gt;notice there is no &lt;code&gt;class&lt;/code&gt; keyword used in the compiled JS code, even though classes were introduced in ES2015. This is one of TypeScript compiler’s features – to produce code which is supported in most of the browsers and JS engines, without having to wait for support of new JavaScript versions&lt;/li&gt;
&lt;li&gt;comments are left untouched&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This explains how the TypeScript compiler works. It also confirms what we stated before, that TypeScript is for programmers. As soon as your code is deployed to production, the types you added in &lt;code&gt;.ts&lt;/code&gt; files are absent. The way this process is built gives a lot of advantages, but it may also be a source of confusion – let’s see how exactly.&lt;/p&gt;

&lt;h2&gt;
  
  
  TypeScript compilation flaws
&lt;/h2&gt;

&lt;p&gt;Finally, knowing how TS -&amp;gt; JS compilation works, let’s quickly explore some of its common flaws.&lt;/p&gt;

&lt;h3&gt;
  
  
  No runtime protection
&lt;/h3&gt;

&lt;p&gt;As you now know, TypeScript stripes out the types during compilation. It means that the information about types is not present at runtime (when our code executes). Because of that, &lt;strong&gt;we are not protected by TypeScript at runtime&lt;/strong&gt;. Consequently, if an input comes from a user and the inputs themselves are not well validated, we may still get runtime type errors. Imagine that your code expects a &lt;code&gt;number&lt;/code&gt;, but the user enters a &lt;code&gt;string&lt;/code&gt; because of lack of proper input validation. TypeScript will not protect you here.&lt;/p&gt;

&lt;p&gt;The same applies to validating API responses. Most data from HTTP APIs comes in a form of JSON. In TypeScript, we can represent such data as &lt;code&gt;type&lt;/code&gt; or &lt;code&gt;interface&lt;/code&gt;. Based on those expected shapes of data, we use objects of a given type and assume that given properties are present on them or not. However, APIs may change, and TypeScript will again not protect us at runtime. We still need to &lt;a href="https://www.codejourney.net/typing-api-responses-with-zod/"&gt;resort to alternative solutions for runtime types validation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;To be completely clear – I don’t think that no runtime protection is something TypeScript lacks. On the contrary – I love the flexibility of TypeScript which this approach gives. It’s just how the language has been designed, and we should be aware of that 🙂&lt;/p&gt;

&lt;h3&gt;
  
  
  Debugging complexity
&lt;/h3&gt;

&lt;p&gt;When working on a TypeScript project, the code you see on production is different from the one in your IDE. Sometimes not only types are stripped out by TypeScript compiler, but as you saw earlier it may also convert some constructs to the other (like changing a &lt;code&gt;class&lt;/code&gt; to a &lt;code&gt;function&lt;/code&gt;). It makes debugging, especially directly on production, more complex.&lt;/p&gt;

&lt;p&gt;In order to place breakpoints and actually have them hit in your TypeScript code, you need &lt;a href="https://code.visualstudio.com/docs/typescript/typescript-debugging#_javascript-source-map-support"&gt;source maps&lt;/a&gt;. It does the job in most cases, but adds to the complexity at the same time, not always working seamlessly.&lt;/p&gt;

&lt;h3&gt;
  
  
  TypeScript is sometimes too strict
&lt;/h3&gt;

&lt;p&gt;If you decide to &lt;a href="https://www.codejourney.net/is-it-worth-migrating-to-typescript/"&gt;migrate your JS project to TypeScript&lt;/a&gt;, you will quickly get frustrated by how strict this new language can be. Especially if you are coming from JavaScript world where &lt;a href="https://www.codejourney.net/10-most-shocking-javascript-features-for-csharp-developers/"&gt;everything is allowed&lt;/a&gt; 😅&lt;/p&gt;

&lt;p&gt;There are countless memes about that, but here is the one I like:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://devs.lol/meme/for-any-emergency-in-typescript-222"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--EcpC-7bi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i0.wp.com/www.codejourney.net/wp-content/uploads/2023/10/typescript-any-type-meme.jpg%3Fresize%3D576%252C505%26ssl%3D1" alt="TypeScript compiler will often let you go with any type" width="576" height="505"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Joking apart, most things TypeScript complaints about can be configured/turned off in &lt;code&gt;tsconfig.json&lt;/code&gt; file. This is actually what I like about TypeScript. It brings static typing into JavaScript world, but lets you control how strict you want it to be. So, if you get frustrated with TypeScript compiler’s complaints, remember about &lt;a href="https://www.typescriptlang.org/docs/handbook/compiler-options.html"&gt;configuration options&lt;/a&gt; 🙂&lt;/p&gt;

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

&lt;p&gt;I hope that now you feel more comfortable working with TypeScript compiler 🙂&lt;/p&gt;

&lt;p&gt;The post &lt;a href="https://www.codejourney.net/typescript-compiler-explained/"&gt;TypeScript Compiler Explained&lt;/a&gt; appeared first on &lt;a href="https://www.codejourney.net"&gt;CodeJourney.net&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>javascript</category>
      <category>typescript</category>
      <category>fullstack</category>
    </item>
    <item>
      <title>What Is A JavaScript Bundler?</title>
      <dc:creator>Dawid Sibiński</dc:creator>
      <pubDate>Sat, 02 Sep 2023 08:16:11 +0000</pubDate>
      <link>https://dev.to/dsibinski/what-is-a-javascript-bundler-429o</link>
      <guid>https://dev.to/dsibinski/what-is-a-javascript-bundler-429o</guid>
      <description>&lt;p&gt;If you asked me 5 years ago what a JavaScript bundler is, I’d probably tell you it’s something people fight with for hours, just to get a simple web app set up 🤪 While this might have been closer to the truth in 2018, a lot has changed in JavaScript ecosystem until today.&lt;/p&gt;

&lt;p&gt;If you’re starting your web development journey, or maybe have already dived into it, but are not really sure what JS bundlers are and what’s their role, you’re reading a proper piece of explanation 🙂&lt;/p&gt;

&lt;h2&gt;
  
  
  Chaos and complexity – the issues
&lt;/h2&gt;

&lt;p&gt;Let’s consider a very simple JavaScript app. We have just one page &lt;code&gt;index.html&lt;/code&gt;. Our HTML is hydrated with &lt;code&gt;index.js&lt;/code&gt; file, which adds some interactivity to it. In order to use it, we need to import &lt;code&gt;index.js&lt;/code&gt; script in &lt;code&gt;index.html&lt;/code&gt; file. We also decided to use an external library (Bootstrap), so we should also link the necessary CSS.&lt;/p&gt;

&lt;p&gt;We are linking the &lt;code&gt;index.js&lt;/code&gt; with a &lt;code&gt;script&lt;/code&gt; tag in &lt;code&gt;head&lt;/code&gt; section:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"module"&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"index.js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt;
      &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css"&lt;/span&gt;
      &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"stylesheet"&lt;/span&gt;
      &lt;span class="na"&gt;integrity=&lt;/span&gt;&lt;span class="s"&gt;"sha384-rbsA2VBKQhggwzxH7pPCaAqO46MgnOM80zW1RWuH61DGLwZJEdK2Kadq2F9CUG65"&lt;/span&gt;
      &lt;span class="na"&gt;crossorigin=&lt;/span&gt;&lt;span class="s"&gt;"anonymous"&lt;/span&gt;
    &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;charset=&lt;/span&gt;&lt;span class="s"&gt;"UTF-8"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"viewport"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"width=device-width, initial-scale=1.0"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;My WebPage&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Of course, as we are building a web application, we won’t put all the JavaScript code in &lt;code&gt;index.js&lt;/code&gt;. That’s why we created two separate files with some functionalities: &lt;code&gt;my-utils.js&lt;/code&gt; and &lt;code&gt;navigation.js&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;For instance, the &lt;code&gt;my-utils.js&lt;/code&gt; exports a few functions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;doSomethingNice&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;alert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Nice!&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="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;notUsedFunctionA&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;alert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Not used function A&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="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;notUsedFunctionB&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;alert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Not used function B&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="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;notUsedFunctionC&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;alert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Not used function C&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice the not used functions there – we’ll get to the point of them soon.&lt;/p&gt;

&lt;p&gt;Next, our &lt;code&gt;index.js&lt;/code&gt; file imports what it needs and adds some interactivity to the HTML elements:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { doSomethingNice } from "./my-utils.js";
import { reloadThePage } from "./navigation.js";

document
  .getElementById("reload-page-btn")
  .addEventListener("click", reloadThePage);

document
  .getElementById("say-sth-nice-btn")
  .addEventListener("click", doSomethingNice);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If we now open our webpage, we can see the network activity when the page is loaded:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi0.wp.com%2Fwww.codejourney.net%2Fwp-content%2Fuploads%2F2023%2F08%2Fhtml-loading-javascript-1.png%3Fresize%3D1131%252C330%26ssl%3D1" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi0.wp.com%2Fwww.codejourney.net%2Fwp-content%2Fuploads%2F2023%2F08%2Fhtml-loading-javascript-1.png%3Fresize%3D1131%252C330%26ssl%3D1" alt="HTML page loading JavaScript files"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Notice that all 3 JavaScript files are fetched separately: &lt;code&gt;index.js&lt;/code&gt;, &lt;code&gt;my-utils.js&lt;/code&gt; and &lt;code&gt;navigation.js&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;What’s more, if you check the contents of &lt;code&gt;my-utils.js&lt;/code&gt;, it obviously loads the whole script, containing even the not used functions:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi0.wp.com%2Fwww.codejourney.net%2Fwp-content%2Fuploads%2F2023%2F08%2Fhtml-utils-fetching-content.png%3Fresize%3D558%252C300%26ssl%3D1" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi0.wp.com%2Fwww.codejourney.net%2Fwp-content%2Fuploads%2F2023%2F08%2Fhtml-utils-fetching-content.png%3Fresize%3D558%252C300%26ssl%3D1" alt="HTML script file content"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I think you might already feel that this can get a little problematic 😉 Imagine managing this when you have hundreds of your own JavaScript files plus dozens of external libraries. Not only will your app be making hundreds of network requests to fetch every single file, but it will always fetch everything – even the stuff your page doesn’t use.&lt;/p&gt;

&lt;p&gt;Here’s where a JavaScript bundler comes into the field.&lt;/p&gt;

&lt;p&gt;You can find full source code of this JavaScript app &lt;a href="https://github.com/dsibinski/codejourney/tree/main/javascript-bundlers/no-bundler-app" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  What does a JavaScript bundler do?
&lt;/h2&gt;

&lt;p&gt;JavaScript bundler produces &lt;em&gt;bundles&lt;/em&gt; 🙂 But what is a bundle? It’s basically a static file, optimized to be served to the client (in our case: a web browser). The main goal is to produce a single bundle file from multiple dependencies. In effect, the user’s browser doesn’t need to fetch so many files separately. But how is such a bundle created?&lt;/p&gt;

&lt;p&gt;First, a JavaScript bundler needs to know the &lt;em&gt;entry point&lt;/em&gt;. It’s a kind of root in which our “code tree” begins. In the case of our sample JavaScript application from the previous paragraph, a perfect candidate for an entry point would be the &lt;code&gt;index.js&lt;/code&gt; file. Modern bundlers support multiple entry points. It can be very useful if you’re building a multipage application, so each page can have its own entry point.&lt;/p&gt;

&lt;p&gt;The next step is to create a dependency graph. The JavaScript bundler is basically starting from the root (entry point) and traverses all dependencies referenced from it, as well as all of these dependencies’ dependencies. Having the dependency graph, bundler knows what is exactly used by what and in which place of our app.&lt;/p&gt;

&lt;p&gt;This is how you can imagine the graph of dependencies:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://paulallies.medium.com/webpack-managing-javascript-and-css-dependencies-3b4913f49c58" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi0.wp.com%2Fwww.codejourney.net%2Fwp-content%2Fuploads%2F2023%2F08%2Fwebpack-dependency-graph.webp%3Fresize%3D858%252C348%26ssl%3D1" alt="webpack - graph of dependencies"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Module bundlers like &lt;a href="https://webpack.js.org/" rel="noopener noreferrer"&gt;webpack&lt;/a&gt; not only know the dependencies of your entry point. These tools even check what each dependency uses. Thanks to building such a detailed dependency graph, the bundler can introduce multiple optimizations into the bundle file.&lt;/p&gt;

&lt;p&gt;Finally, JavaScript bundler outputs the actual bundles. As I mentioned, bundles can be highly optimized by applying techniques like &lt;a href="https://webpack.js.org/guides/code-splitting/" rel="noopener noreferrer"&gt;code splitting&lt;/a&gt;, &lt;a href="https://vitejs.dev/guide/features.html#css" rel="noopener noreferrer"&gt;CSS inlining&lt;/a&gt;, &lt;a href="https://parceljs.org/features/development/#hot-reloading" rel="noopener noreferrer"&gt;HMR&lt;/a&gt; and various performance optimizations.&lt;/p&gt;

&lt;p&gt;JavaScript bundler might also ensure the backwards-compatibility with older web browsers by converting some newer JavaScript constructs used in your code to their equivalents from previous JS versions.&lt;/p&gt;

&lt;p&gt;What’s interesting, modern bundlers can handle not only JS files, but also CSS, HTML and even images.&lt;/p&gt;

&lt;h2&gt;
  
  
  JavaScript bundler in action
&lt;/h2&gt;

&lt;p&gt;Currently, the most popular JavaScript bundles is (still) &lt;a href="https://webpack.js.org/" rel="noopener noreferrer"&gt;webpack&lt;/a&gt;. It has been the first really advanced bundler created for both the browser and NodeJS.&lt;/p&gt;

&lt;p&gt;You might have heard unpleasant things about webpack and in fact, its configuration can get really &lt;em&gt;spaghetti&lt;/em&gt; 🤪 There are simpler alternatives out there, but let’s start with what’s the most common tool used in web development today.&lt;/p&gt;

&lt;h3&gt;
  
  
  Adding webpack to a JavaScript app
&lt;/h3&gt;

&lt;p&gt;Our sample app already has a &lt;code&gt;package.json&lt;/code&gt; file (we used JavaScript modules), so we can install webpack with this command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install --save-dev webpack webpack-cli
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we should reorganize the files a bit. Let’s put all scripts in &lt;code&gt;src&lt;/code&gt; folder and move &lt;code&gt;index.html&lt;/code&gt; to &lt;code&gt;dist&lt;/code&gt; folder. Finally, it looks like that:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi0.wp.com%2Fwww.codejourney.net%2Fwp-content%2Fuploads%2F2023%2F08%2Fwebpack-app-structure.png%3Fresize%3D241%252C217%26ssl%3D1" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi0.wp.com%2Fwww.codejourney.net%2Fwp-content%2Fuploads%2F2023%2F08%2Fwebpack-app-structure.png%3Fresize%3D241%252C217%26ssl%3D1" alt="Webpack app structure"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Using the folder named &lt;code&gt;dist&lt;/code&gt; is very common. It stands for &lt;em&gt;distributable&lt;/em&gt;, which means the code ready to be distributed = served to the public. This is where our bundles will be located. As the &lt;code&gt;index.html&lt;/code&gt; is directly served to the public, we also place it there.&lt;/p&gt;

&lt;p&gt;With such a folders structure, there’s nothing more we need to configure for webpack to work. By default, webpack looks for &lt;code&gt;src/index.js&lt;/code&gt; file which we already have and outputs bundles into the &lt;code&gt;dist&lt;/code&gt; folder. To use more advanced features or multiple entry points, a &lt;a href="https://dev.to/godspowercuche/6-ways-to-configure-webpack-28k4-temp-slug-4390628"&gt;configuration file should be added&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In our case, let’s go with the zero-config approach. The only thing we need is to add a &lt;code&gt;script&lt;/code&gt; entry to &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 json"&gt;&lt;code&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"scripts"&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;"build"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"webpack"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"test"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"echo &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;Error: no test specified&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt; &amp;amp;&amp;amp; exit 1"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let’s now run &lt;code&gt;npm run build&lt;/code&gt; and see what happens:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi0.wp.com%2Fwww.codejourney.net%2Fwp-content%2Fuploads%2F2023%2F08%2Fwebpack-build-output.png%3Fresize%3D483%252C154%26ssl%3D1" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi0.wp.com%2Fwww.codejourney.net%2Fwp-content%2Fuploads%2F2023%2F08%2Fwebpack-build-output.png%3Fresize%3D483%252C154%26ssl%3D1" alt="Webpack build output"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It seems that webpack created the &lt;code&gt;main.js&lt;/code&gt; asset (bundle):&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi0.wp.com%2Fwww.codejourney.net%2Fwp-content%2Fuploads%2F2023%2F08%2Fwebpack-main-bundle.png%3Fresize%3D351%252C245%26ssl%3D1" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi0.wp.com%2Fwww.codejourney.net%2Fwp-content%2Fuploads%2F2023%2F08%2Fwebpack-main-bundle.png%3Fresize%3D351%252C245%26ssl%3D1" alt="webpack main bundle"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let’s make sure that our &lt;code&gt;index.html&lt;/code&gt; page links this bundle file properly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;html&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"en"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"module"&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"main.js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, let’s open our &lt;code&gt;index.html&lt;/code&gt; page and see how the network requests look like now:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi0.wp.com%2Fwww.codejourney.net%2Fwp-content%2Fuploads%2F2023%2F08%2Fwebpack-app-bundle-fetching-network.png%3Fresize%3D1138%252C283%26ssl%3D1" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi0.wp.com%2Fwww.codejourney.net%2Fwp-content%2Fuploads%2F2023%2F08%2Fwebpack-app-bundle-fetching-network.png%3Fresize%3D1138%252C283%26ssl%3D1" alt="webpack app - network activity fetching bundles"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Wow, that’s something different from what we had previously! Notice that now only 1 script, the &lt;code&gt;main.js&lt;/code&gt; file, is fetched by the webpage. There were 3 before: &lt;code&gt;index.js&lt;/code&gt;, &lt;code&gt;my-utils.js&lt;/code&gt; and &lt;code&gt;navigation.js&lt;/code&gt;. Of course, the web page works exactly as before.&lt;/p&gt;

&lt;p&gt;Let us also examine the contents of the fetched &lt;code&gt;main.js&lt;/code&gt; file:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi0.wp.com%2Fwww.codejourney.net%2Fwp-content%2Fuploads%2F2023%2F08%2Fwebpack-app-main-bundle-content.png%3Fresize%3D942%252C248%26ssl%3D1" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi0.wp.com%2Fwww.codejourney.net%2Fwp-content%2Fuploads%2F2023%2F08%2Fwebpack-app-main-bundle-content.png%3Fresize%3D942%252C248%26ssl%3D1" alt="webpack app main.js bundle content"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Pay attention what happened here. Webpack has nicely inlined all the external code we used directly into the &lt;code&gt;main.js&lt;/code&gt; bundle. What’s more, the exported, but not used functions from &lt;code&gt;my-utils.js&lt;/code&gt; are not present here at all! When building the dependency graph, webpack noticed that those functions are not used, so it didn’t include them 😉&lt;/p&gt;

&lt;p&gt;This is basically how webpack and most JavaScript bundlers work. Their role is to deliver the smallest and the most optimized bundles possible. This ultimately saves a lot of bandwidth by avoiding unnecessary network requests the client browser would otherwise need to make. Cutting out the unused code makes the bundles smaller, again reducing the network usage.&lt;/p&gt;

&lt;p&gt;You can find full source code of the webpack app &lt;a href="https://github.com/dsibinski/codejourney/tree/main/javascript-bundlers/webpack-app" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Webpack has a lot more to offer
&lt;/h3&gt;

&lt;p&gt;From all the JavaScript bundlers used today, webpack is the most advanced one. It’s the most mature one as well. It offers dozens of customizations, &lt;a href="https://webpack.js.org/concepts/#plugins" rel="noopener noreferrer"&gt;plugins&lt;/a&gt; and &lt;a href="https://webpack.js.org/concepts/#loaders" rel="noopener noreferrer"&gt;loaders&lt;/a&gt;. You can also easily add &lt;a href="https://www.codejourney.net/is-it-worth-migrating-to-typescript/" rel="noopener noreferrer"&gt;TypeScript&lt;/a&gt; support.&lt;/p&gt;

&lt;p&gt;You can do really crazy stuff with webpack 😉 However, if you are starting your web development journey, don’t get overwhelmed by learning it all. Just be aware that webpack can do almost everything you might need. It’s just a matter of &lt;a href="https://stackoverflow.com/questions/tagged/webpack" rel="noopener noreferrer"&gt;searching StackOverflow&lt;/a&gt; or asking &lt;a href="https://github.com/features/copilot" rel="noopener noreferrer"&gt;Copilot&lt;/a&gt; 😉&lt;/p&gt;

&lt;h3&gt;
  
  
  Alternatives to webpack
&lt;/h3&gt;

&lt;p&gt;In recent years, developers created a few other amazing JavaScript bundlers. I recommend you to pay attention to them, because webpack doesn’t have to be your first choice today. Webpack is still &lt;a href="https://create-react-app.dev/" rel="noopener noreferrer"&gt;used in CRA&lt;/a&gt;, which is believed to be a default way of creating new React applications. This is what makes it very widely used, but you don’t need to follow this path 🙂&lt;/p&gt;

&lt;p&gt;I recommend checking &lt;a href="https://parceljs.org/" rel="noopener noreferrer"&gt;Parcel&lt;/a&gt;, &lt;a href="https://esbuild.github.io/" rel="noopener noreferrer"&gt;esbuild&lt;/a&gt; and &lt;a href="https://vitejs.dev/" rel="noopener noreferrer"&gt;ViteJS&lt;/a&gt;. These are modern bundlers created to, among others, eliminate some of webpack’s burdens. If you’re starting out and don’t want to get yourself busy with bundling configuration, I especially recommend creating your next app with Parcel.&lt;/p&gt;

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

&lt;p&gt;That’s all that you need to know about JavaScript bundlers to be able to work with them and understand what’s happening when executing this magic &lt;code&gt;npm run build&lt;/code&gt; script 😉&lt;/p&gt;

&lt;p&gt;The post &lt;a href="https://www.codejourney.net/what-is-a-javascript-bundler/" rel="noopener noreferrer"&gt;What Is A JavaScript Bundler?&lt;/a&gt; appeared first on &lt;a href="https://www.codejourney.net" rel="noopener noreferrer"&gt;CodeJourney.net&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>javascript</category>
      <category>roadtodotnetfullstack</category>
      <category>webpack</category>
    </item>
    <item>
      <title>How (And Why?) To Wrap External Libraries?</title>
      <dc:creator>Dawid Sibiński</dc:creator>
      <pubDate>Mon, 20 Feb 2023 18:40:00 +0000</pubDate>
      <link>https://dev.to/dsibinski/how-and-why-to-wrap-external-libraries-59hn</link>
      <guid>https://dev.to/dsibinski/how-and-why-to-wrap-external-libraries-59hn</guid>
      <description>&lt;p&gt;If you use external libraries in your application, wrapping them may be very helpful. How to wrap external libraries and why it’s worth doing that? Today we’re going to dive into that, based on a TypeScript web app example 😉&lt;/p&gt;

&lt;h2&gt;
  
  
  Why?
&lt;/h2&gt;

&lt;p&gt;You probably know what a &lt;em&gt;wrapper&lt;/em&gt; is. As its name suggests, it’s a practice of putting another layer on a piece of something. In our case, &lt;em&gt;wrapping&lt;/em&gt; a piece of code in another piece of code 🙂&lt;/p&gt;

&lt;p&gt;But why would you do that? To make your life easier! 💪 &lt;br&gt;
Wrapping external libraries lets you abstract your code from their implementation details. In effect, it makes your life a lot easier when you want to keep the behavior, but change the library providing it. This approach also lets you use only those features from a given external dependency that you actually need.&lt;br&gt;&lt;br&gt;
Let’s see that with an example.&lt;/p&gt;
&lt;h2&gt;
  
  
  Wrapping HTTP client
&lt;/h2&gt;

&lt;p&gt;A very good example is HTTP client wrapper. HTTP calls are used in almost every web application. In order to perform them, we need to choose an HTTP client. We can either use &lt;code&gt;fetch&lt;/code&gt;, or something more sophisticated like &lt;code&gt;axios&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;However, with time, we may decide to replace it with something else. There might be many reasons for that – either the library stops to be maintained or something new and better is out there. It would be a shame if we’d now need to change the code in those thousands of places where the current library is being used. This would take a lot of time and might be error-prone. We can definitely prepare better for such cases 😉&lt;/p&gt;
&lt;h3&gt;
  
  
  Create HttpClient wrapper for axios
&lt;/h3&gt;

&lt;p&gt;Let’s say that, for now, we will go with &lt;code&gt;axios&lt;/code&gt;. Instead of &lt;a href="https://axios-http.com/docs/example" rel="noopener noreferrer"&gt;calling it directly from our code&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ProductsList.tsx – calling axios directly from component's code &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;useEffect&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&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;axios&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;axios&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Product&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;../types/product&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;DummyJsonProductsResult&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;../types/dummyJsonProductsResult&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ProductsList&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;products&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setProducts&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Product&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="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;axios&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;DummyJsonProductsResult&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;("https://dummyjson.com/products")
      .then((result) =&amp;gt; &lt;span class="si"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;setProducts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;products&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="si"&gt;}&lt;/span&gt;);
  }, []);

 // ...
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I will create an &lt;em&gt;HttpClient&lt;/em&gt; wrapper for it and use it instead.&lt;/p&gt;

&lt;p&gt;First, I create &lt;code&gt;httpClient.ts&lt;/code&gt; file in &lt;code&gt;wrappers&lt;/code&gt; folder. I like to have such a catalog in my React projects and keep all the wrappers there.&lt;/p&gt;

&lt;p&gt;I start writing all wrappers with an interface. In that case, I treat the interface as a &lt;em&gt;contract&lt;/em&gt;. It should say what I need this small wrapper to do, without worrying about implementation details.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;IHttpClient&lt;/code&gt; interface initially looks as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// httpClient.ts – IHttpClient interface (get only)&lt;/span&gt;
&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;IHttpClient&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;TResponse&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;(url: string): Promise&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;TResponse&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That’s what we have so far. We just need to retrieve the data with &lt;code&gt;GET&lt;/code&gt; method.&lt;/p&gt;

&lt;p&gt;Next step is to create the actual implementation of &lt;code&gt;IHttpClient&lt;/code&gt; using &lt;code&gt;axios&lt;/code&gt;. This is pretty straightforward using a &lt;code&gt;class&lt;/code&gt; implementing &lt;code&gt;IHttpClient&lt;/code&gt; interface and taking a look at &lt;a href="https://axios-http.com/docs/instance" rel="noopener noreferrer"&gt;&lt;code&gt;axios&lt;/code&gt;‘s documentation&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// httpClient.ts – AxiosHttpClient implementation (get only)&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AxiosHttpClient&lt;/span&gt; &lt;span class="k"&gt;implements&lt;/span&gt; &lt;span class="nx"&gt;IHttpClient&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;private&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;AxiosInstance&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;get&lt;/span&gt; &lt;span class="nf"&gt;axiosClient&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nx"&gt;AxiosInstance&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;instance&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;initAxiosClient&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nf"&gt;initAxiosClient&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;axios&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;TResponse&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;(url: string): Promise&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;TResponse&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="si"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&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;TResponse&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;resolve&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;reject&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;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;axiosClient&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;TResponse&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;AxiosResponse&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;TResponse&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;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="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;result&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;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&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;catch&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Error&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nx"&gt;AxiosError&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;reject&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="p"&gt;});&lt;/span&gt;
  &lt;span class="si"&gt;}&lt;/span&gt;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This implementation lets us encapsulate a simple singleton inside the class.&lt;/p&gt;

&lt;p&gt;The last step here is to expose the instance of our HTTP client. Remember to &lt;strong&gt;always export the interface type variable&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;const&lt;/span&gt; &lt;span class="nx"&gt;httpClient&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;IHttpClient&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;AxiosHttpClient&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That’s basically how we wrap external libraries in TypeScript. Easy-peasy 😉&lt;/p&gt;

&lt;h3&gt;
  
  
  Using the wrapper
&lt;/h3&gt;

&lt;p&gt;I can now use our wrapper in &lt;code&gt;ProductsList.tsx&lt;/code&gt; component:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ProductsList.tsx – using IHttpClient wrapper&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;useEffect&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&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="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;httpClient&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;../wrappers/httpClient&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// we don't import axios here anymore&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;Product&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;../types/product&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;DummyJsonProductsResult&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;../types/dummyJsonProductsResult&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ProductsList&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;products&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setProducts&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Product&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="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;httpClient&lt;/span&gt; &lt;span class="c1"&gt;// instead of axios, we use our wrapper in components&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;DummyJsonProductsResult&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;("https://dummyjson.com/products")
      .then((result) =&amp;gt; &lt;span class="si"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;setProducts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;products&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="si"&gt;}&lt;/span&gt;);
  }, []);

 // ...
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice how easy that was. Since now, we only import stuff from &lt;code&gt;axios&lt;/code&gt; package in &lt;code&gt;httpClient.ts&lt;/code&gt; file. Only this single file is dependent on &lt;a href="https://www.npmjs.com/package/axios" rel="noopener noreferrer"&gt;&lt;code&gt;axios&lt;/code&gt; npm package&lt;/a&gt;. None of our components (and other project files) know about &lt;code&gt;axios&lt;/code&gt;. Our IDE only knows that the wrapper is an object instance fulfilling &lt;code&gt;IHttpClient&lt;/code&gt; contract:&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%2Fz3k5ake36u79uc1tj4i9.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%2Fz3k5ake36u79uc1tj4i9.png" alt="Interface-implementing wrapper instance usage in Visual Studio Code" width="537" height="332"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Extra wrapper features
&lt;/h3&gt;

&lt;p&gt;Apart from nicely isolating us from dependencies, wrappers have more advantages. One of them is a possibility to configure the library in a single place. In our example with &lt;code&gt;axios&lt;/code&gt; – imagine that one day you want to add custom headers to each HTTP request. Having all API calls going via &lt;code&gt;AxiosHttpClient&lt;/code&gt;, you can configure such things there, in a single place. That way, you follow the &lt;a href="https://en.wikipedia.org/wiki/Don%27t_repeat_yourself" rel="noopener noreferrer"&gt;DRY principle&lt;/a&gt; and keep all the logic related to &lt;code&gt;axios&lt;/code&gt; (or to any other external dependency) in a single place. It also comes with benefits like easy testability etc.&lt;/p&gt;

&lt;p&gt;For clarity, I also added &lt;code&gt;post&lt;/code&gt; support to our &lt;code&gt;IHttpClient&lt;/code&gt;. You can &lt;a href="https://github.com/dsibinski/codejourney/commit/200f31ba0c5483f3e834a5ec4cd82566887e3d98" rel="noopener noreferrer"&gt;check it here&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Replacing the wrapped library
&lt;/h2&gt;

&lt;p&gt;Ok, it’s time to have our solution battle-tested. We have the HTTP client nicely wrapped and exposed as an instance of &lt;code&gt;IHttpClient&lt;/code&gt;. However, we came to the conclusion that &lt;code&gt;axios&lt;/code&gt; is not good enough, and we want to have it replaced with &lt;code&gt;fetch&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Remember that in the real web application, you would have hundreds or thousands of usages of &lt;code&gt;IHttpClient&lt;/code&gt; instance. That’s where the power of wrappers comes into play 😎&lt;/p&gt;

&lt;p&gt;So how do I make sure those thousands of usages will now use &lt;code&gt;fetch&lt;/code&gt; instead of &lt;code&gt;axios&lt;/code&gt;? That’s actually pretty straightforward. I’ll simply add a new class – &lt;code&gt;FetchHttpClient&lt;/code&gt; implementing &lt;code&gt;IHttpClient&lt;/code&gt; interface:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// httpClient.ts – new FetchHttpClient using fetch for get and post&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;FetchHttpClient&lt;/span&gt; &lt;span class="k"&gt;implements&lt;/span&gt; &lt;span class="nx"&gt;IHttpClient&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;TResponse&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;(url: string): Promise&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;TResponse&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="si"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&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;TResponse&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;resolve&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;reject&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;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="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;response&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;response&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;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;responseJson&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;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;responseJson&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;TResponse&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;catch&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Error&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;reject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Response JSON parsing error: &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="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="p"&gt;})&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Error&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;reject&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="p"&gt;});&lt;/span&gt;
  &lt;span class="si"&gt;}&lt;/span&gt;

  post&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;TResponse&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;(url: string, data?: object): Promise&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;TResponse&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="si"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&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;TResponse&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;resolve&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;reject&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;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="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Content-Type&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;application/json&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&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="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
          &lt;span class="nx"&gt;response&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;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;responseJson&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;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;responseJson&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;TResponse&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;catch&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Error&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;reject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Response JSON parsing error: &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="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="p"&gt;})&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Error&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;reject&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="p"&gt;});&lt;/span&gt;
  &lt;span class="si"&gt;}&lt;/span&gt;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For completion, I included &lt;code&gt;POST&lt;/code&gt; here as well.&lt;/p&gt;

&lt;p&gt;The one last thing I have to do to make our new &lt;code&gt;FetchHttpClient&lt;/code&gt; be used in the whole app in place of &lt;code&gt;AxiosHttpClient&lt;/code&gt; is to change a single line with export:&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;httpClient&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;IHttpClient&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;FetchHttpClient&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// instead of new AxiosHttpClient()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and that’s it! Our whole application now uses &lt;code&gt;fetch&lt;/code&gt; for &lt;code&gt;GET&lt;/code&gt; and &lt;code&gt;POST&lt;/code&gt; HTTP requests 🙂 And it even still works 😅&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary and source code
&lt;/h2&gt;

&lt;p&gt;I hope that now you see how important it is to wrap external libraries. We have seen that on JavaScript/TypeScript app example, but this is applicable to any programming language and framework.&lt;/p&gt;

&lt;p&gt;It’s always good to be as independent as possible of 3rd party stuff. Too many times I’ve been in a situation that some &lt;code&gt;npm&lt;/code&gt; package is so extensively used in a project, directly in the source code in hundreds of places, that it cannot be replaced without spending several days on it. Creating wrappers forces us to think abstract, which is another great advantage.&lt;/p&gt;

&lt;p&gt;You can find the complete source code here: &lt;a href="https://github.com/dsibinski/codejourney/tree/main/wrapping-external-libraries" rel="noopener noreferrer"&gt;https://github.com/dsibinski/codejourney/tree/main/wrapping-external-libraries&lt;/a&gt;&lt;/p&gt;

</description>
      <category>programming</category>
      <category>designpatterns</category>
      <category>javascript</category>
      <category>npm</category>
    </item>
    <item>
      <title>Adding Meatballs Menu To React-Table Rows</title>
      <dc:creator>Dawid Sibiński</dc:creator>
      <pubDate>Mon, 06 Feb 2023 16:46:17 +0000</pubDate>
      <link>https://dev.to/dsibinski/adding-meatballs-menu-to-react-table-rows-4kaj</link>
      <guid>https://dev.to/dsibinski/adding-meatballs-menu-to-react-table-rows-4kaj</guid>
      <description>&lt;p&gt;Meatballs menu (⋯), also called &lt;em&gt;three horizontal dots menu&lt;/em&gt;, is a great way of providing contextual options for grid rows. In this article, I will show you how to add the meatballs menu to a table built with &lt;a href="https://www.npmjs.com/package/@tanstack/react-table"&gt;@tanstack/react-table&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;After reading this article, you will know how to add such a menu to your React app. The end result will look as in the highlighted picture of this article 😉&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating a table with row selection support
&lt;/h2&gt;

&lt;p&gt;First, let’s define a type of data that we want to display. For our example, we will display a list of &lt;code&gt;Car&lt;/code&gt;s:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Car.ts&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Car&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;id&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="nl"&gt;brand&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="nl"&gt;model&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="nl"&gt;productionYear&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="nl"&gt;isAvailable&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, we create a new component called &lt;code&gt;CarsTable&lt;/code&gt;, responsible for rendering the table. We will use &lt;a href="https://www.npmjs.com/package/@tanstack/react-table"&gt;@tanstack/react-table&lt;/a&gt; for the table behavior and &lt;a href="https://www.npmjs.com/package/react-bootstrap"&gt;react-bootstrap&lt;/a&gt; for UI elements.&lt;/p&gt;

&lt;p&gt;I implemented the &lt;code&gt;CarsTable&lt;/code&gt; component in &lt;a href="https://tanstack.com/table/v8/docs/examples/react/basic"&gt;quite a standard way according to react-table docs&lt;/a&gt;, so I won’t copy-paste it here. You can check the whole component’s code &lt;a href="https://github.com/dsibinski/react-table-context-menu/blob/faccde72b4be060c9dbca3d59d7b1506bc9f9b01/src/components/CarsTable.tsx"&gt;here&lt;/a&gt;. What’s interesting is that I added support for row selection in a way that makes our table a &lt;a href="https://reactjs.org/docs/forms.html#controlled-components"&gt;controlled React component&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// CarsTable.tsx – controlled row selection &lt;/span&gt;
&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;CarsTableProps&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;selectedCar&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Car&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;onCarSelected&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;car&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Car&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="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;CarsTable&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;CarsTableProps&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="c1"&gt;// ...&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;tbody&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;table&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getRowModel&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;row&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;isActive&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;row&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;original&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;selectedCar&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="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;tr&lt;/span&gt;
              &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;row&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
              &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;isActive&lt;/span&gt; &lt;span class="o"&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="na"&gt;backgroundColor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#3a7a11&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="kc"&gt;undefined&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
              &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="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;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onCarSelected&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;row&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;original&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
              &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
            &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
              &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;row&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getVisibleCells&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;cell&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;td&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;cell&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                  &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;flexRender&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cell&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;column&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;columnDef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cell&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;cell&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getContext&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
                &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;td&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
              &lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;tr&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;})&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;tbody&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="c1"&gt;// ...&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see, &lt;code&gt;selectedCar&lt;/code&gt; and &lt;code&gt;onCarSelected&lt;/code&gt; are managed from outside. See settings the &lt;code&gt;style&lt;/code&gt; - this is how the row color gets changed for the currently selected car. I recently had to deal with such a case in one of my projects.&lt;/p&gt;

&lt;p&gt;So far, so good. This is how it looks, populated with sample data:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--fgWl3sd9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i0.wp.com/www.codejourney.net/wp-content/uploads/2023/02/1_InitialTable.png%3Fresize%3D991%252C440%26ssl%3D1" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--fgWl3sd9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i0.wp.com/www.codejourney.net/wp-content/uploads/2023/02/1_InitialTable.png%3Fresize%3D991%252C440%26ssl%3D1" alt="react-table table with row selection support" width="880" height="391"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Adding meatballs menu
&lt;/h2&gt;

&lt;p&gt;Ok, we have a table. Now we want to add the meatballs menu. We need a three dots icon and a dropdown menu to open on clicking it.&lt;/p&gt;

&lt;p&gt;After quickly &lt;a href="https://react-bootstrap.github.io/components/dropdowns/"&gt;going through the react-bootstrap docs&lt;/a&gt;, let’s create a new component for that:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// CarRowContextMenu.tsx&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;Dropdown&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-bootstrap&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Car&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;../types/Car&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;CustomDivToggle&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;./CustomDivToggle&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;BsThreeDots&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-icons/bs&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;CarRowContextMenu&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;carRow&lt;/span&gt; &lt;span class="p"&gt;}:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;carRow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Car&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Dropdown&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;carRow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Dropdown&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Toggle&lt;/span&gt; &lt;span class="na"&gt;as&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;CustomDivToggle&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;cursor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;pointer&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;BsThreeDots&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Dropdown&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Toggle&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Dropdown&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Menu&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Dropdown&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Item&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Option 1&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Dropdown&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Item&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Dropdown&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Item&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Option 2&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Dropdown&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Item&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Dropdown&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Menu&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Dropdown&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As we want our dropdown toggle to have custom style, I had to provide &lt;code&gt;CustomDivToggle&lt;/code&gt; as a &lt;a href="https://react-bootstrap.github.io/components/dropdowns/#custom-dropdown-components"&gt;custom dropdown component&lt;/a&gt;. It’s nothing very interesting, but you can check its implementation &lt;a href="https://github.com/dsibinski/react-table-context-menu/blob/c98687413a28eecfc5fa4175a4b55a79dee8300f/src/components/CustomDivToggle.tsx"&gt;here&lt;/a&gt; 😉&lt;/p&gt;

&lt;p&gt;Next, as we’d like our meatballs menu to be an additional column in the grid, it seems natural to &lt;a href="https://tanstack.com/table/v8/docs/guide/column-defs#column-def-types"&gt;use &lt;code&gt;react-table&lt;/code&gt;‘s display column&lt;/a&gt;. Let’s try adding it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// CarsTable.tsx – adding meatballs menu with display-type column&lt;/span&gt;
&lt;span class="nx"&gt;columnHelper&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;display&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;context-menu&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;cell&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cellContext&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;row&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;cellContext&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;row&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;original&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;CarRowContextMenu&lt;/span&gt; &lt;span class="na"&gt;carRow&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;row&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;;&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;}),&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It looks we have it:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--f5L6pUMl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i0.wp.com/www.codejourney.net/wp-content/uploads/2023/02/3_ContextMenuAddedV1.png%3Fresize%3D984%252C442%26ssl%3D1" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--f5L6pUMl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i0.wp.com/www.codejourney.net/wp-content/uploads/2023/02/3_ContextMenuAddedV1.png%3Fresize%3D984%252C442%26ssl%3D1" alt="Meatballs menu added to the table with react-tabe's display column" width="880" height="395"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;However, after clicking through it for a while, it seems we have an issue. The toggle only opens on every 2nd click:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--A2br-zgy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://i0.wp.com/www.codejourney.net/wp-content/uploads/2023/02/4_ContextMenuDoubleClickIssue.gif%3Fresize%3D1140%252C498%26ssl%3D1" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--A2br-zgy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://i0.wp.com/www.codejourney.net/wp-content/uploads/2023/02/4_ContextMenuDoubleClickIssue.gif%3Fresize%3D1140%252C498%26ssl%3D1" alt="Meatballs menu with react-table's display column. Double-click issue" width="880" height="384"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Why is that? The reason is our controlled &lt;code&gt;CarsTable&lt;/code&gt; component. On clicking a new row, the change event occurs, which triggers the re-render of the &lt;code&gt;CarsTable&lt;/code&gt; component (because &lt;code&gt;selectedCar&lt;/code&gt; &lt;em&gt;actually&lt;/em&gt; changes). It makes &lt;code&gt;react-table&lt;/code&gt; re-render the table, with the meatballs menu in its default state (collapsed). On clicking the menu in the same row again, the change event occurs, but the &lt;code&gt;selectedCar&lt;/code&gt; &lt;em&gt;does not actually change&lt;/em&gt;, which &lt;em&gt;does not&lt;/em&gt; trigger the re-render. Initially, it took me a while to figure that out 😀&lt;/p&gt;

&lt;h2&gt;
  
  
  Fixing double-click issue
&lt;/h2&gt;

&lt;p&gt;In our case, a fix for the double click issue is quite simple. Instead of adding the column with the menu using &lt;code&gt;columnHelper.display()&lt;/code&gt; function from &lt;code&gt;react-table&lt;/code&gt;, we can render it &lt;em&gt;manually&lt;/em&gt;. To do that, we should simply add a new &lt;code&gt;&amp;lt;td&amp;gt;&lt;/code&gt; to each row of the table:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// CarsTable.tsx – context menu added as a separate &amp;lt;td&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;tbody&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;table&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getRowModel&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;row&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;isActive&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;row&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;original&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;selectedCar&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="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;tr&lt;/span&gt;
              &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;row&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
              &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;isActive&lt;/span&gt; &lt;span class="o"&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="na"&gt;backgroundColor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#3a7a11&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="kc"&gt;undefined&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
              &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="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;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onCarSelected&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;row&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;original&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
              &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
            &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
              &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;row&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getVisibleCells&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;cell&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;td&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;cell&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                  &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;flexRender&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cell&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;column&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;columnDef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cell&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;cell&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getContext&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
                &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;td&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
              &lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
              &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;td&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;CarRowContextMenu&lt;/span&gt; &lt;span class="na"&gt;carRow&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;row&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;original&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
              &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;td&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;tr&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;})&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;tbody&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Additionally, to make it work, we need an additional table’s header placeholder:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// CarsTable.tsx – placeholder &amp;lt;th&amp;gt; for context menu&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;thead&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;table&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getHeaderGroups&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;headerGroup&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;tr&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;headerGroup&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;headerGroup&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;header&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
              &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;th&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;header&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;header&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isPlaceholder&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="nx"&gt;flexRender&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                      &lt;span class="nx"&gt;header&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;column&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;columnDef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;header&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                      &lt;span class="nx"&gt;header&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getContext&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
                    &lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
              &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;th&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
            &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* placeholder header for context menu */&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;th&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;th&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;tr&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;thead&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That’s it! Our &lt;code&gt;react-table&lt;/code&gt; table with row selection support and the meatballs menu works like a charm now:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--G4682apz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://i0.wp.com/www.codejourney.net/wp-content/uploads/2023/02/5_ContextMenuFinalVersion-1.gif%3Fresize%3D1140%252C493%26ssl%3D1" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--G4682apz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://i0.wp.com/www.codejourney.net/wp-content/uploads/2023/02/5_ContextMenuFinalVersion-1.gif%3Fresize%3D1140%252C493%26ssl%3D1" alt="react-table table with row selection and meatballs menu - final version" width="880" height="380"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Meatballs menu with react-table – source code
&lt;/h2&gt;

&lt;p&gt;You can find the complete &lt;a href="https://github.com/dsibinski/react-table-context-menu"&gt;source code here&lt;/a&gt;. I hope you find it useful! 🙂&lt;/p&gt;

</description>
      <category>programming</category>
      <category>bootstrap</category>
      <category>javascript</category>
      <category>react</category>
    </item>
    <item>
      <title>10 VS Code Extensions I Couldn’t Live Without</title>
      <dc:creator>Dawid Sibiński</dc:creator>
      <pubDate>Thu, 19 Jan 2023 19:12:07 +0000</pubDate>
      <link>https://dev.to/dsibinski/10-vs-code-extensions-i-couldnt-live-without-4npa</link>
      <guid>https://dev.to/dsibinski/10-vs-code-extensions-i-couldnt-live-without-4npa</guid>
      <description>&lt;p&gt;I love VS Code 😍 There’s no better web code editor out there for me. Today, I’m going to share with you the 10 VS Code extensions that make my life easier. I can’t imagine coding without them. Let’s dive into it!&lt;/p&gt;

&lt;h2&gt;
  
  
  1. &lt;a href="https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode" rel="noopener noreferrer"&gt;Prettier&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;My number one. I was a bit skeptical initially, but today I can’t imagine my life without Prettier 😀 For those unfamiliar with the tool, Prettier is an &lt;em&gt;opinionated&lt;/em&gt; code formatted. Opinionated, because it allows for almost no configuration. It reformats your code automatically based on its own rules.&lt;/p&gt;

&lt;p&gt;It may sound scary and limiting, but it really frees your mind. Suddenly you forget about all those &lt;em&gt;spaces vs tabs wars&lt;/em&gt; and discussions on which column shall the code be wrapped. Prettier does that all automatically. It can even be done on saving the file! If you haven't yet, you should definitely give Prettier a try.&lt;/p&gt;

&lt;p&gt;It is also very easy to &lt;a href="https://prettier.io/docs/en/precommit.html" rel="noopener noreferrer"&gt;execute prettier formatting with pre-commit git hook&lt;/a&gt;, so the checked-in code is always formatted, even if some team members don’t use it in their IDE.&lt;/p&gt;

&lt;p&gt;Never again without Prettier! 🙂&lt;/p&gt;

&lt;h2&gt;
  
  
  2. &lt;a href="https://marketplace.visualstudio.com/items?itemName=dsznajder.es7-react-js-snippets" rel="noopener noreferrer"&gt;ES7+ React/Redux/React-Native snippets&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;This is one of the first VS Code extensions I installed. It’s simple, yet very powerful! This plugin adds multiple JavaScript/React snippets. I create many new components every day. Snippets make it very easy:&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%2Frblc7vhtcguc6b5hc8oe.gif" 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%2Frblc7vhtcguc6b5hc8oe.gif" alt="One of the VS Code extensions that adds React snippets" width="932" height="487"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I recommend trying this extension out and exploring its built-in snippets.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. &lt;a href="https://marketplace.visualstudio.com/items?itemName=adrianwilczynski.csharp-to-typescript" rel="noopener noreferrer"&gt;C# to TypeScript&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;This one is a time-saver for .NET developers working with TypeScript. It allows generating TypeScript interfaces from C# classes. You can simply copy a C# &lt;code&gt;class&lt;/code&gt; and paste is as a TypeScript’s &lt;code&gt;interface&lt;/code&gt; in Visual Studio Code:&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%2Fgz40oge2hvbta89ggua5.gif" 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%2Fgz40oge2hvbta89ggua5.gif" alt="Copying C# code to TypeScript" width="1005" height="431"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can also paste using keyboard shortcuts. There’s even &lt;a href="https://www.nuget.org/packages/CSharpToTypeScript.CLITool/" rel="noopener noreferrer"&gt;a CLI tool&lt;/a&gt; available in case you’d want to automate this process. This extension doesn’t support all scenarios (especially no support for &lt;code&gt;records&lt;/code&gt; 😭), but it still covers most simple copy-paste cases. By the way, synchronizing C# with TypeScript types is one of the challenges for full stack .NET developers.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. &lt;a href="https://marketplace.visualstudio.com/items?itemName=mattpocock.ts-error-translator" rel="noopener noreferrer"&gt;Total TypeScript&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;From all VS Code extensions I use, this is the only one that actually helps me learn on the job. It was called &lt;em&gt;TypeScript Error Translator&lt;/em&gt; before, and this is what I initially used it for. It basically provides more meaningful, crowdsourced translations for often enigmatic TypeScript errors:&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%2Fsguvkz8miowamgnqb1yq.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%2Fsguvkz8miowamgnqb1yq.png" alt="TypeScript error translator shows nice explanation of TS error" width="800" height="272"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When a translation is missing, you can always contribute one. Additionally, as its new name suggests, it also lets you learn programming concepts directly inside your code. As soon as it finds a new concept in the code, a brief explanation is shown:&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%2F19h7mcvauryw88qdszu3.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%2F19h7mcvauryw88qdszu3.png" alt="Total Typescript extension shows new TS concepts explanations in VS Code" width="800" height="378"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It will stop highlighting this particular type of concept as soon as you mark it as learned. I think it’s a quite interesting way of learning on the job 😉&lt;/p&gt;

&lt;h2&gt;
  
  
  5. &lt;a href="https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint" rel="noopener noreferrer"&gt;ESLint&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;This is the extension for integrating the most well-known linter for JavaScript into Visual Studio Code. &lt;a href="https://eslint.org/" rel="noopener noreferrer"&gt;ESLint&lt;/a&gt; is a static analyzer of your source code which helps you find problems quickly. It will highlight issues in your code for all loaded files from your workspace. I don’t feel there’s much to write about here – just &lt;a href="https://eslint.org/" rel="noopener noreferrer"&gt;check their website&lt;/a&gt; and give this extension a try 😉&lt;/p&gt;

&lt;h2&gt;
  
  
  6. &lt;a href="https://marketplace.visualstudio.com/items?itemName=rangav.vscode-thunder-client" rel="noopener noreferrer"&gt;Thunder Client&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Thunder Client is like &lt;a href="https://www.postman.com/" rel="noopener noreferrer"&gt;Postman&lt;/a&gt;, but built into VS Code. It lets you easily play with HTTP APIs. You can create your own collections of requests and export them to JSON, which can be checked into the source control.&lt;/p&gt;

&lt;p&gt;Yet another very useful extension! 👍&lt;/p&gt;

&lt;h2&gt;
  
  
  7. &lt;a href="https://marketplace.visualstudio.com/items?itemName=zenclabs.previewjs" rel="noopener noreferrer"&gt;Preview.js&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;This is one of my recent discoveries. Preview.js allows to live-preview React, Solid or Vue components directly in VS Code. It also generates the initial props data, sometimes even for complex objects:&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%2Fi0.wp.com%2Fwww.codejourney.net%2Fwp-content%2Fuploads%2F2023%2F01%2F6_VSCode_PreviewJS-2.gif%3Fresize%3D1140%252C593%26ssl%3D1" 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%2Fi0.wp.com%2Fwww.codejourney.net%2Fwp-content%2Fuploads%2F2023%2F01%2F6_VSCode_PreviewJS-2.gif%3Fresize%3D1140%252C593%26ssl%3D1" alt="PreviewJS working in VS Code" width="760" height="395"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The plugin is also configurable for custom scenarios like external dependencies. You can find more information &lt;a href="https://previewjs.com/docs/config" rel="noopener noreferrer"&gt;in the documentation&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  8. &lt;a href="https://marketplace.visualstudio.com/items?itemName=WakaTime.vscode-wakatime" rel="noopener noreferrer"&gt;WakaTime&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;If you like analytics, you should check this VS Code extension. WakaTime measures how much time you spend actually writing code. It shows exactly in which language you programmed for how much time. It also divides time entries into projects you worked on:&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%2Fejxaohnrof1ivlsazxp8.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%2Fejxaohnrof1ivlsazxp8.png" alt="WakaTime sample statistics" width="800" height="714"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It’s interesting to get such insights “for free” and see how little time we spend &lt;em&gt;actually&lt;/em&gt; coding 😀 Try it for yourself and let me know your results!&lt;/p&gt;

&lt;h2&gt;
  
  
  9. &lt;a href="https://marketplace.visualstudio.com/items?itemName=zhuangtongfa.Material-theme" rel="noopener noreferrer"&gt;One Dark Pro&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Who never started a new project by installing fancy tools, text editors or choosing the best color theme for your IDE? 😄 Of course – good colors = smooth -and pleasant – coding 😎 One Dark Pro is a must-have theme for my Visual Studio Code. I love it, it makes source code much more readable for me. What’s your favorite color theme for VS Code? 😉&lt;/p&gt;

&lt;h2&gt;
  
  
  10. &lt;a href="https://marketplace.visualstudio.com/items?itemName=vscode-icons-team.vscode-icons" rel="noopener noreferrer"&gt;vscode-icons&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Last but not least, a good friend to the One Dard Pro theme, legendary VS Code icons set. It has over 13M installs! 🤯&lt;/p&gt;

&lt;p&gt;Apart from getting +100 fanciness 😉, it makes icons more explicit in the explorer:&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%2Ftip0rhl2fzmul2l6477v.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%2Ftip0rhl2fzmul2l6477v.png" alt="vscode-icons - icons examples in VS Code explorer" width="599" height="612"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you can see, it even guesses the folder type based on its name – see &lt;code&gt;types&lt;/code&gt; or &lt;code&gt;utils&lt;/code&gt; folders’ icons above.&lt;/p&gt;

&lt;p&gt;Not critical, yet helpful. Undeniably adds a million to your professionalism as a web developer 😎😎😎&lt;/p&gt;

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

&lt;p&gt;So, that’s it! The list of my 10 favorite Visual Studio Code extensions.&lt;/p&gt;

&lt;p&gt;What about you? What are your must-have VS Code extensions? 😉&lt;/p&gt;

</description>
      <category>programming</category>
      <category>javascript</category>
      <category>react</category>
      <category>roadtodotnetfullstack</category>
    </item>
    <item>
      <title>How To Fix Visual Studio Code IntelliSense Loading Infinitely</title>
      <dc:creator>Dawid Sibiński</dc:creator>
      <pubDate>Sun, 09 Oct 2022 08:57:31 +0000</pubDate>
      <link>https://dev.to/dsibinski/how-to-fix-visual-studio-code-intellisense-loading-infinitely-do9</link>
      <guid>https://dev.to/dsibinski/how-to-fix-visual-studio-code-intellisense-loading-infinitely-do9</guid>
      <description>&lt;p&gt;Continuing with &lt;a href="https://www.codejourney.net/how-to-fix-npm-err-enoent-enoent-no-such-file-or-directory-rename/"&gt;weird errors you might encounter in JavaScript world&lt;/a&gt;, I have another one: &lt;strong&gt;Visual Studio Code IntelliSense loading infinitely&lt;/strong&gt;😀Solution included, of course!&lt;/p&gt;

&lt;p&gt;The symptoms of this issue are putting your mouse on something where you’d expect the IntelliSense guidelines, but instead you only see the “Loading…” text.&lt;/p&gt;

&lt;p&gt;In this short article, I’m sharing the reason of this issue and my way of fixing it.&lt;/p&gt;

&lt;h2&gt;
  
  
  How VS Code Infinite IntelliSense Loading Looks Like
&lt;/h2&gt;

&lt;p&gt;This is what I struggled with:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--sIm4fXjl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://i0.wp.com/www.codejourney.net/wp-content/uploads/2022/10/2_VSCodeLoadingIssue.gif%3Fresize%3D497%252C907%26ssl%3D1" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--sIm4fXjl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://i0.wp.com/www.codejourney.net/wp-content/uploads/2022/10/2_VSCodeLoadingIssue.gif%3Fresize%3D497%252C907%26ssl%3D1" alt="Visual Studio Code IntelliSense Loading Infinitely - a gif animation" width="497" height="907"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you can see, I didn’t get any IntelliSense while hovering my mouse on various elements in the editor.&lt;/p&gt;

&lt;p&gt;A similar thing happened when I tried to use &lt;code&gt;Go to References&lt;/code&gt; (or &lt;code&gt;Shift&lt;/code&gt; + &lt;code&gt;F12&lt;/code&gt; on Windows) for any object:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--t0t5R11u--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://i0.wp.com/www.codejourney.net/wp-content/uploads/2022/10/3_VSCode_find_references_loading.gif%3Fresize%3D509%252C907%26ssl%3D1" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--t0t5R11u--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://i0.wp.com/www.codejourney.net/wp-content/uploads/2022/10/3_VSCode_find_references_loading.gif%3Fresize%3D509%252C907%26ssl%3D1" alt="Visual Studio Code IntelliSense Loading Infinitely for Go to References - a gif animation" width="509" height="907"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you can see, the loading bar at the top of VS Code was showing progress infinitely.&lt;/p&gt;

&lt;p&gt;Let’s now see how to fix this annoying issue 😉&lt;/p&gt;

&lt;h2&gt;
  
  
  Fixing Visual Studio Code IntelliSense Loading Infinitely
&lt;/h2&gt;

&lt;p&gt;After quite long investigation, I finally found the reason. It turned out that &lt;strong&gt;&lt;a href="https://code.visualstudio.com/docs/typescript/typescript-compiling#_using-newer-typescript-versions"&gt;sometimes your Visual Studio Code might be using a different TypeScript version than your workspace uses&lt;/a&gt;&lt;/strong&gt;. In my case, it was exactly the cause of the infinite loading problem 🧐&lt;/p&gt;

&lt;p&gt;In order to fix it, use &lt;code&gt;TypeScript: Select TypeScript Version...&lt;/code&gt; command. You can access commands with &lt;code&gt;Ctrl + Shift + P&lt;/code&gt; on Windows or &lt;code&gt;⇧⌘P&lt;/code&gt; on Mac:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--HvXZqTtt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i0.wp.com/www.codejourney.net/wp-content/uploads/2022/10/5_SelectTypeScriptVersion.png%3Fresize%3D600%252C262%26ssl%3D1" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--HvXZqTtt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i0.wp.com/www.codejourney.net/wp-content/uploads/2022/10/5_SelectTypeScriptVersion.png%3Fresize%3D600%252C262%26ssl%3D1" alt='Visual Studio Code: command palette view, "TypeScript: Select TypeScript Version" command' width="600" height="262"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Select this command and tell Visual Studio Code to use the workspace version of TypeScript:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--G3JkZyZS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i0.wp.com/www.codejourney.net/wp-content/uploads/2022/10/6_SelectTypeScriptVersion_UseWorkspaceVersion.png%3Fresize%3D627%252C139%26ssl%3D1" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--G3JkZyZS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i0.wp.com/www.codejourney.net/wp-content/uploads/2022/10/6_SelectTypeScriptVersion_UseWorkspaceVersion.png%3Fresize%3D627%252C139%26ssl%3D1" alt='Visual Studio Code: command palette view, "TypeScript: Select TypeScript Version" command, telling VS Code to use workspace version of TypeScript' width="627" height="139"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you can see on the screenshot above, in my case the VS Code’s TypeScript version was &lt;code&gt;4.8.2&lt;/code&gt;, while the workspace version was &lt;code&gt;4.8.3&lt;/code&gt;. Changing it to use the newer, workspace version solved the problem. Visual Studio Code IntelliSense loading infinitely issue was gone 🎉&lt;/p&gt;

&lt;p&gt;If it doesn’t work straightaway, you might need restarting your VS Code editor.&lt;/p&gt;

&lt;p&gt;I hope that worked for you and saved you some hours of debugging and exploring StackOverflow 🙂&lt;/p&gt;

</description>
      <category>programming</category>
      <category>intellisense</category>
      <category>javascript</category>
      <category>typescript</category>
    </item>
    <item>
      <title>Improve your tests with Assert Object Pattern</title>
      <dc:creator>Dawid Sibiński</dc:creator>
      <pubDate>Fri, 29 Jul 2022 16:42:34 +0000</pubDate>
      <link>https://dev.to/dsibinski/improve-your-tests-with-assert-object-pattern-4jlc</link>
      <guid>https://dev.to/dsibinski/improve-your-tests-with-assert-object-pattern-4jlc</guid>
      <description>&lt;p&gt;Today I’d like to share with you a very interesting concept in software testing – Assert Object pattern. It makes the &lt;em&gt;Assert&lt;/em&gt; part of a test much simpler and more readable. Let’s dive right into it !😉&lt;/p&gt;

&lt;h2&gt;
  
  
  The Asserts Hell
&lt;/h2&gt;

&lt;p&gt;Let’s consider the following unit test:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;What’s wrong here? &lt;em&gt;Given&lt;/em&gt; and &lt;em&gt;When&lt;/em&gt; sections are great single-liners. We know straightaway what’s the input and the action executed. However, &lt;em&gt;Then&lt;/em&gt; block is too complex. It’s hard to figure out, just passing quickly through this test, what is &lt;em&gt;expected&lt;/em&gt;. This case is even not that bad thanks to the usage of &lt;a href="https://fluentassertions.com/"&gt;FluentAssertions&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I spend a lot of time writing tests, but I spend even more time reading them. I always hope that I will find these &lt;em&gt;idyllic&lt;/em&gt; tests that act as code documentation… 🧐&lt;/p&gt;

&lt;p&gt;However, let’s go step by step. Some time ago I attended a software testing course. That’s where I discovered the solution to &lt;em&gt;The Asserts Hell&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Assert Object for Better Asserts
&lt;/h2&gt;

&lt;p&gt;Assert Object pattern is what solves our problem. The idea is to create an &lt;em&gt;Assert&lt;/em&gt; class which wraps the original object being tested. In our case, the tested object is of &lt;strong&gt;Product&lt;/strong&gt; class, so our assert class will be called &lt;strong&gt;ProductAssert&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Let’s see the implementation:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;As you can see, we simply moved the asserts from our test’s &lt;em&gt;Then&lt;/em&gt; section into &lt;strong&gt;ProductAssert&lt;/strong&gt; class’s methods. Additionally, we always return &lt;em&gt;this&lt;/em&gt; from each asserting method, which allows chaining functions calls.&lt;/p&gt;

&lt;p&gt;We can now use such assert object in our unit test:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;You must agree, it’s much more readable now !😉&lt;/p&gt;

&lt;p&gt;We can of course improve it even more, for example by wrapping these 3 assertion methods (&lt;strong&gt;BeAvailable()&lt;/strong&gt;, &lt;strong&gt;HaveDiscount()&lt;/strong&gt; and &lt;strong&gt;Cost()&lt;/strong&gt;) into a single one. We can also easily create an &lt;a href="https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/extension-methods"&gt;extension method&lt;/a&gt; for the &lt;strong&gt;Product&lt;/strong&gt; class itself, so the assert object doesn’t have to be instantiated in our unit test. I could even add an extension to &lt;em&gt;FluentAssertions&lt;/em&gt; library.&lt;/p&gt;

&lt;p&gt;You can find complete source code used as examples in this article &lt;a href="https://github.com/dsibinski/Playground/tree/main/Playground/Playground.Tests"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Assert Object – summary
&lt;/h2&gt;

&lt;p&gt;I personally find Assert Object a very useful tests code refactoring method. As a programmer, you spend most of your time not on writing, but on reading the source code. Clear and simple tests can make your (and your colleagues’) life much better !😉&lt;/p&gt;

&lt;p&gt;Of course, the Assert Object pattern should not be your default way of asserting. If you can complete your test with one or two assertions, then it’s probably better to keep it without wrapping into any additional objects. Having too many &lt;em&gt;assert&lt;/em&gt; statements might also mean that the objects being tested are poorly designed. However, as we often work with legacy code which we can’t easily change or refactor, it might be a good solution.&lt;/p&gt;

&lt;p&gt;What patterns for writing better tests do you use? Share your tips in the comments!&lt;/p&gt;

&lt;p&gt;The post &lt;a href="https://www.codejourney.net/2020/11/improve-your-tests-with-assert-object-pattern/"&gt;Improve your tests with Assert Object Pattern&lt;/a&gt; appeared first on &lt;a href="https://www.codejourney.net"&gt;CodeJourney.net&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>dotnet</category>
      <category>csharp</category>
      <category>tests</category>
      <category>testing</category>
    </item>
    <item>
      <title>Typing API Responses With Zod</title>
      <dc:creator>Dawid Sibiński</dc:creator>
      <pubDate>Fri, 15 Jul 2022 04:54:07 +0000</pubDate>
      <link>https://dev.to/dsibinski/typing-api-responses-with-zod-526f</link>
      <guid>https://dev.to/dsibinski/typing-api-responses-with-zod-526f</guid>
      <description>&lt;p&gt;Have you ever needed to synchronize types in your frontend app with the backend API?&lt;/p&gt;

&lt;p&gt;If you ever had an API action defined like that in your controller:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;and fetched this data using TypeScript in the following way:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;at some point, you probably also experienced the desynchronization of backend (C#, in our example) and frontend (TypeScript) types definitions. What if someone has changed the C# version of &lt;code&gt;UserViewModel&lt;/code&gt;, but no one corrected its TypeScript’s equivalent?&lt;/p&gt;

&lt;p&gt;Your TypeScript fetching code will tell nothing about that. &lt;strong&gt;There will be no error, even though the fetched data doesn’t match the expected &lt;code&gt;UserViewModel&lt;/code&gt; type&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;I’ll try to address this issue in this article 🙂 Let’s see how typing API responses with &lt;code&gt;zod&lt;/code&gt; can help us here.&lt;/p&gt;

&lt;h2&gt;
  
  
  Synchronization of Backend and Frontend API Typings
&lt;/h2&gt;

&lt;p&gt;First, why would we want to keep the backend and frontend models in sync?&lt;/p&gt;

&lt;p&gt;For me, that’s the purpose of using TypeScript. &lt;strong&gt;We want our code to be as well-typed as possible&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;For instance, we normally want the data displayed to the user to be fully typed. TypeScript enhances our programming experience by providing us with typing information. Thanks to that, we know &lt;em&gt;what is what and what contains what&lt;/em&gt;. We also express what types of data we expect in particular cases.&lt;/p&gt;

&lt;p&gt;The APIs mostly return JSON data, which can be anything. Because of that, it is much easier to have the data returned from the API fully typed in TypeScript. Thanks to that, &lt;strong&gt;we know what properties are available on the data models received from the API and whether we can use and display them to the users&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The sample code used within this article is available &lt;a href="https://github.com/dsibinski/DotNetReactZodApp"&gt;on GitHub&lt;/a&gt;. We will use ASP.NET Core (C#) and React (TypeScript) apps as examples.&lt;/p&gt;

&lt;h2&gt;
  
  
  Models Synchronization Example
&lt;/h2&gt;

&lt;p&gt;As we saw in the beginning, a classic example is an API controller that returns a strongly-typed data:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;The returned data type is a collection of &lt;code&gt;UserViewModel&lt;/code&gt; objects. Here’s the C# definition of this type:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Its equivalent is also defined on TypeScript side:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h2&gt;
  
  
  Usage in TypeScript
&lt;/h2&gt;

&lt;p&gt;Cool. With this simple code, we can create a &lt;code&gt;usersService.ts&lt;/code&gt; file and fetch our users’ data from the API. Notice how we make this call strongly typed:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Everything looks legit. We can use the data retrieved from the API in &lt;code&gt;UsersList&lt;/code&gt; component and everything is nicely typed:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--3vl9jldb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/a4vssbf7xu5a0cd56ie1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--3vl9jldb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/a4vssbf7xu5a0cd56ie1.png" alt="UsersList React component" width="736" height="403"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The data is even perfectly displayed:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--AFXoU_V_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/y3o7ykryqtxvlqthc2uz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--AFXoU_V_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/y3o7ykryqtxvlqthc2uz.png" alt="Table with users rendered on the web page" width="880" height="353"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So, what can go wrong here? 🤔&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem – Typings’ Desynchronization
&lt;/h2&gt;

&lt;p&gt;Let’s say that a backend developer implements a requirement to rename “loyalty points” into “fidelity points”. Easy. (S)he renames &lt;code&gt;LoyaltyPoints&lt;/code&gt; property in the C#’s &lt;code&gt;UserViewModel&lt;/code&gt; to &lt;code&gt;FidelityPoints&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The new C# model looks as follows:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Nice! The backend dev is a very good programmer, so (s)he even launches the React web application to make sure that everything still works correctly and there are no errors in the dev console:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--nW2svRAQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/naao5kw5sl4l0itmsnjy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--nW2svRAQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/naao5kw5sl4l0itmsnjy.png" alt='Table of users rendered on the web page with empty "Loyalty points" column and no errors on Chrome DevTools console' width="880" height="367"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After a quick look, everything looks awesome. The users list is displayed, there are no errors in the console. Apparently, these test users don’t have any loyalty points assigned – that’s why the empty values in “Loyalty points” column. What’s more, translators will update the column’s translation later. We are good! Let’s go on prod! 😎&lt;/p&gt;

&lt;p&gt;I guess you already know what went wrong here. &lt;strong&gt;API definition changed, but TypeScript didn’t inform us about that&lt;/strong&gt; 😔 Our &lt;code&gt;UserViewModel&lt;/code&gt; still uses the old property name:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--I-tyw4Cr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ciu5ilzdu9ehp5t7jdoo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--I-tyw4Cr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ciu5ilzdu9ehp5t7jdoo.png" alt="UserViewModel typescript type definition" width="508" height="290"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;However, it still works. When rendering the &lt;code&gt;UsersList&lt;/code&gt;, we simply get &lt;code&gt;undefined&lt;/code&gt; in place of &lt;code&gt;loyaltyPoints&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--DFS-V1of--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/y6ikh6k3vsn8o0fitmon.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--DFS-V1of--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/y6ikh6k3vsn8o0fitmon.png" alt="UsersList rendering at runtime. user.loyaltyPoints property is always undefined" width="661" height="313"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the end, &lt;a href="https://www.codejourney.net/2018/11/10-most-shocking-javascript-features-for-csharp-developers/"&gt;this is all JavaScript there&lt;/a&gt;. What’s interesting, the renamed &lt;code&gt;fidelityPoints&lt;/code&gt; property is already there at runtime:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--v__MHfnE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4i7huf3sso1c18pudwsu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--v__MHfnE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4i7huf3sso1c18pudwsu.png" alt="At runtime we can see the new fidelityPoints property already present" width="441" height="239"&gt;&lt;/a&gt;&lt;br&gt;
but no one cared about it 😔&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;With the current solution, we will never be informed soon enough about API models changes in our React application&lt;/strong&gt;. In the best case, we’ll get an &lt;code&gt;undefiend&lt;/code&gt; or &lt;code&gt;null&lt;/code&gt; error when clicking through the app. However, it’s usually an end user who finds such problems on production. This is definitely not what we want 😶&lt;/p&gt;

&lt;p&gt;We can solve this problem by typing API responses with &lt;a href="https://github.com/colinhacks/zod"&gt;zod&lt;/a&gt;. Let’s now see how to do that.&lt;/p&gt;
&lt;h2&gt;
  
  
  The Solution – zod
&lt;/h2&gt;

&lt;p&gt;Our remedy – &lt;code&gt;zod&lt;/code&gt; – is quite a &lt;a href="https://www.npmjs.com/package/zod"&gt;decent npm package&lt;/a&gt; with ~600k weekly downloads. Its GitHub page advertises the library as &lt;em&gt;TypeScript-first schema validation with static type inference&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;You can definitely do many things with zod. It can be used together with libraries like &lt;a href="https://react-hook-form.com/"&gt;react-hook-form&lt;/a&gt; to perform complex forms validation. However, in our case, &lt;strong&gt;we’ll treat &lt;code&gt;zod&lt;/code&gt; as a solution for better typings in TypeScript&lt;/strong&gt;.&lt;/p&gt;
&lt;h3&gt;
  
  
  Adding zod to React app
&lt;/h3&gt;

&lt;p&gt;First, let’s install &lt;code&gt;zod&lt;/code&gt; into our React application:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm i zod
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  First Schema Definition with zod
&lt;/h3&gt;

&lt;p&gt;With &lt;code&gt;zod&lt;/code&gt;, we define our types in a slightly different way. Instead of creating a &lt;code&gt;type&lt;/code&gt; or &lt;code&gt;interface&lt;/code&gt; directly, we first create a &lt;em&gt;schema&lt;/em&gt;. In our case, we can define a &lt;code&gt;UserViewModelSchema&lt;/code&gt; using &lt;code&gt;z.object&lt;/code&gt; creator function:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;p&gt;Few interesting parts here:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;Line 2&lt;/em&gt;: notice how &lt;code&gt;zod&lt;/code&gt; helps us to define types like &lt;code&gt;Guid&lt;/code&gt; with built-in schemas like &lt;code&gt;uuid()&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Line 8&lt;/em&gt;: first, I used &lt;code&gt;AddressViewModelSchema&lt;/code&gt; here. This is a custom schema of an &lt;code&gt;AddressViewModel&lt;/code&gt; object, which is another type used internally in &lt;code&gt;UserViewModel&lt;/code&gt;. You can use such custom schemas in other schemas. Also notice the &lt;code&gt;nullable()&lt;/code&gt; call here, which makes the address property nullable&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;First step done – we have our &lt;code&gt;UserViewModelSchema&lt;/code&gt;. But can we use it instead of &lt;code&gt;UserViewModel&lt;/code&gt; type? Not really. Schema is used for validation purposes only. We still need the &lt;code&gt;UserViewModel&lt;/code&gt; TypeScript’s type.&lt;/p&gt;

&lt;h3&gt;
  
  
  Inferring Type From zod’s Schema
&lt;/h3&gt;

&lt;p&gt;Fortunately, &lt;code&gt;zod&lt;/code&gt; comes with a handy &lt;code&gt;z.infer&lt;/code&gt; function that allows us to &lt;em&gt;infer&lt;/em&gt; the type from the schema.&lt;/p&gt;

&lt;p&gt;Finally, the &lt;code&gt;userViewModel.ts&lt;/code&gt; file looks as follows:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;We can use the exported &lt;code&gt;UserViewModel&lt;/code&gt; type as previously used type. It’s an equivalent to the previous, "classic" type we had defined, but this time inferred from &lt;code&gt;UserViewModelSchema&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Validating API Eesponses With zod Schema
&lt;/h3&gt;

&lt;p&gt;One last step is to make use of &lt;code&gt;UserViewModelSchema&lt;/code&gt;. Let’s modify the &lt;code&gt;getAllUsers&lt;/code&gt; function from &lt;code&gt;usersService&lt;/code&gt; to validate the data received from the API against our schema:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Notice the usage of &lt;code&gt;z.array&lt;/code&gt;. This function call tells &lt;code&gt;zod&lt;/code&gt; to validate an array of objects meeting the rules defined by &lt;code&gt;UserViewModelSchema&lt;/code&gt;, not a single object.&lt;/p&gt;

&lt;p&gt;Now, let’s run our React app and see what happens when we click the “Fetch users” button:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--e_3hNA6v--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5ypn6937o90mln23oya1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--e_3hNA6v--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5ypn6937o90mln23oya1.png" alt="zod throws schema validation error on Chrome dev tools console" width="651" height="592"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is awesome! Exactly what we wanted – a &lt;strong&gt;schema validation error for API response&lt;/strong&gt;. Notice how the &lt;strong&gt;error message precisely points to the missing (or wrong, in other cases) property&lt;/strong&gt;. It tells us we expected a &lt;code&gt;number&lt;/code&gt; called &lt;code&gt;loyaltyPoints&lt;/code&gt;, but instead we received &lt;code&gt;undefined&lt;/code&gt;. The reason for this error message is that the &lt;code&gt;loyaltyPoints&lt;/code&gt; field is &lt;code&gt;Required&lt;/code&gt; in our schema.&lt;/p&gt;

&lt;p&gt;After renaming &lt;code&gt;loyaltyPoints&lt;/code&gt; to &lt;code&gt;fidelityPoints&lt;/code&gt; in &lt;code&gt;UserViewModelSchema&lt;/code&gt; and updating the &lt;code&gt;UsersList&lt;/code&gt; component accordingly, everything works fine again.&lt;/p&gt;

&lt;p&gt;We are now fully typed and prepared for the future, in case an issue with desynchronization of frontend and backend typings happens again 🚀&lt;/p&gt;

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

&lt;p&gt;Today, we’ve seen how typing API responses with &lt;code&gt;zod&lt;/code&gt; can help us detect frontend and backend models desynchronization. Schema validation throws errors when the data doesn’t match its expected shape.&lt;/p&gt;

&lt;p&gt;Remember that &lt;code&gt;zod&lt;/code&gt; is an extended library with many options. I recommend &lt;a href="https://github.com/colinhacks/zod"&gt;exploring them&lt;/a&gt; on your own. An interesting feature we didn’t cover in this article is &lt;a href="https://github.com/colinhacks/zod#strict"&gt;strict mode&lt;/a&gt;, which doesn’t allow additional fields not present in the schema definition when validating the data object.&lt;/p&gt;

&lt;p&gt;The open question remains whether to use schema validation on production. One could think that it’s better to not throw any validation errors, &lt;em&gt;because JavaScript may just work&lt;/em&gt;. However, I think that throwing an error is always better than &lt;em&gt;silently&lt;/em&gt; letting things through. An error lets programmers, automated tests or manual testers to detect the issue before the end user does 😉&lt;/p&gt;

&lt;p&gt;You can explore the complete code presented in this article &lt;a href="https://github.com/dsibinski/DotNetReactZodApp"&gt;here&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>typescript</category>
      <category>react</category>
      <category>dotnet</category>
    </item>
  </channel>
</rss>
