<?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: Tiago Ferreira</title>
    <description>The latest articles on DEV Community by Tiago Ferreira (@tiagof).</description>
    <link>https://dev.to/tiagof</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%2F246656%2F71e152a0-0f53-48d5-bbd4-7726ba607533.JPG</url>
      <title>DEV Community: Tiago Ferreira</title>
      <link>https://dev.to/tiagof</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/tiagof"/>
    <language>en</language>
    <item>
      <title>Elevate Your React Code: Tackling Prop Drilling</title>
      <dc:creator>Tiago Ferreira</dc:creator>
      <pubDate>Mon, 29 Jan 2024 16:00:00 +0000</pubDate>
      <link>https://dev.to/tiagof/elevate-your-react-code-tackling-prop-drilling-26e0</link>
      <guid>https://dev.to/tiagof/elevate-your-react-code-tackling-prop-drilling-26e0</guid>
      <description>&lt;p&gt;Either by our own hand or by others, we have all seen code along the lines of:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ComponentA&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="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;visible&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setVisibility&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="c1"&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;ComponentB&lt;/span&gt; &lt;span class="na"&gt;visible&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;visible&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ComponentB&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="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="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ComponentC&lt;/span&gt; &lt;span class="na"&gt;visible&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&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;visible&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ComponentC&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="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="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;visible&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;
  &lt;span class="c1"&gt;//...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Seems pretty innocent, right? Well, this seemingly reasonable example is actually an anti-pattern called Prop Drilling. Let's dive into what that means and how to avoid it!&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Prop Drilling?
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;“Prop drilling” is the act of passing props from parent to child for multiple layers without modification.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In the example given above, the &lt;code&gt;visible&lt;/code&gt; prop was drilled from ComponentA to ComponentB to ComponentC without modification.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why does this matter?
&lt;/h3&gt;

&lt;p&gt;Prop Drilling is regarded as an anti-pattern for React since it can negatively impact the performance and maintainability of your code.&lt;/p&gt;

&lt;p&gt;At a high level, Prop Drilling can cause performance issues since it can cause unnecessary re-rendering of components. This happens because React will re-render a component if any of its props change. If a component is passed a prop that it doesn't use, it will still re-render when that prop changes. This may not be a big deal for small applications, but can become a major issue for large applications that contain many expensive-to-render components.&lt;/p&gt;

&lt;p&gt;On the maintainability side of things, Prop Drilling introduces dependencies between components that may not be obvious. This can make it difficult to refactor code quickly; which can be killer when developing new features.&lt;/p&gt;

&lt;p&gt;If you wish to level up your React code, you should be aware of when you use Prop Drilling and be considerate of other approaches that can solve the problem at hand.&lt;/p&gt;

&lt;h2&gt;
  
  
  How does Prop Drilling creep into code?
&lt;/h2&gt;

&lt;p&gt;Prop Drilling can be nefarious and creep into code unexpectedly. It requires vigilance in order to avoid it. Let's go through an example!&lt;/p&gt;




&lt;blockquote&gt;
&lt;p&gt;The following parts reference interactive examples that are available on &lt;a href="https://ferreira.io/posts/prop-drilling"&gt;ferreira.io&lt;/a&gt;. Gifs have been used in their place, but the sample app and code tabs for each interactive example are only available in the original published article.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h3&gt;
  
  
  Part 1: Setting Up Our Layout
&lt;/h3&gt;

&lt;p&gt;To start out, let's provide some context for the example that we'll be using! We are building a simple web app with some containers, buttons, and text. Nothing is currently hooked up, so there isn't much functionality, but we can get a general sense of what the application, component hierarchy, and code looks like:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F01pz9kvf62js9a9va79e.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F01pz9kvf62js9a9va79e.gif" alt="Component flamegraph where all components can be forcibly re-rendered with a click." width="618" height="427"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The cursor icon on the top-right of each component indicates that an onClick handler has been set for that component.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;All of the components have been given a default &lt;code&gt;onClick&lt;/code&gt; handler for this first example. If you click on any of the components in the component hierarchy view, it will forcibly re-render that component which can be seen from the flash of green. You'll also see the number of times a component re-rendered in the bottom right-hand-side of each component.&lt;/p&gt;

&lt;h3&gt;
  
  
  Part 2: Adding Component State
&lt;/h3&gt;

&lt;p&gt;Let's upgrade our application a little! We'll add some state to the Button component. This state will control a component's theme (which can be 'light' mode or 'dark' mode):&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl4pklt23u1hdh6f99whj.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl4pklt23u1hdh6f99whj.gif" alt="Component flamegraph where clicking on the button toggles its component state between 'light' and 'dark'. Only the button component re-renders." width="618" height="427"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Reminder: clicking on the components from here on out will not forcibly re-render them (though they may re-render due to state update or changed props)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Wonderful! To start, we have set the &lt;code&gt;onClick&lt;/code&gt; for the Button component to toggle the theme. If you click on Button, you'll notice that the theme for that component changes and things look good!&lt;/p&gt;

&lt;h3&gt;
  
  
  Part 3: Pulling Up State
&lt;/h3&gt;

&lt;p&gt;Let's now integrate some more components into our theme. We can start by pulling up the component state to the SettingsPage component so that we can pass the data down to its children. Then we can pass the theme's toggle function down so that our button components can update the theme:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3xhioyqltziif73g3p1w.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3xhioyqltziif73g3p1w.gif" alt="Component flamegraph where state is within the SettingsPage. Clicking the button component re-renders all components due to render cascades." width="618" height="427"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Both IconButton and Button can update the theme in SettingsPage if you click on them.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Awesome, this works as expected! But interestingly enough, all of the child components of SettingsPage are re-rendering every time the theme changes.&lt;/p&gt;

&lt;p&gt;This happens because React will re-render children components whenever a parent component re-renders. State updates will cause a component to re-render and thus this causes a cascade of re-renders.&lt;/p&gt;

&lt;p&gt;Though this is generally really fast, it can cause performance problems for large applications. Sometimes, you only need data in certain places, and having everything else re-render just for a small change can be expensive. So let's try to do some optimizations!&lt;/p&gt;

&lt;h3&gt;
  
  
  Part 4: React memo
&lt;/h3&gt;

&lt;p&gt;React provides a nice utility wrapper for components called &lt;a href="https://react.dev/reference/react/memo"&gt;&lt;code&gt;memo&lt;/code&gt;&lt;/a&gt;. This utility prevents a component from re-rendering &lt;strong&gt;unless&lt;/strong&gt; the props passed in have changed. At first glance, this sounds perfect for us, so let's try to wrap &lt;strong&gt;all&lt;/strong&gt; of our components with it:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr57yet4l4esnc62dxlxp.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr57yet4l4esnc62dxlxp.gif" alt="Component flamegraph where all the components that have the on-click prop re-renders when clicking to toggle the theme." width="618" height="427"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Huh, we still see a lot of components re-rendering even though we only pass the theme's toggle function down, what gives?&lt;/p&gt;

&lt;h3&gt;
  
  
  Part 5: React useCallback
&lt;/h3&gt;

&lt;p&gt;The important thing to realize is that &lt;code&gt;memo&lt;/code&gt; uses &lt;a href="http://Object.is"&gt;&lt;code&gt;Object.is&lt;/code&gt;&lt;/a&gt; for equality checking. In Javascript, primitives (like number, string, boolean) will be checked by value equality. However, objects, arrays, and functions are checked by reference equality. This means that code that defines a function will have a different reference to that function every time it's called. Thus reference equality checks will fail.&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;123&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;123&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="c1"&gt;// true (values are the same)&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;A1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;a&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;123&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nx"&gt;A1&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nx"&gt;A1&lt;/span&gt; &lt;span class="c1"&gt;// true (references are the same)&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;A2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;a&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;123&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nx"&gt;A2&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nx"&gt;A2&lt;/span&gt; &lt;span class="c1"&gt;// true (references are the same)&lt;/span&gt;

&lt;span class="nx"&gt;A1&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nx"&gt;A2&lt;/span&gt; &lt;span class="c1"&gt;// false (references are different even if contents are the same)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When our SettingsPage component re-renders, it ends up creating a new toggle function each time. This means that when &lt;code&gt;memo&lt;/code&gt; checks the props, it sees that the function reference is different and re-renders the component.&lt;/p&gt;

&lt;p&gt;One way we can fix this issue is by using the &lt;code&gt;useCallback&lt;/code&gt; hook from React. By wrapping our toggle function in that, we can maintain a stable reference which prevents the components from re-rendering:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd0onsdoixqsy9eh1ex82.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd0onsdoixqsy9eh1ex82.gif" alt="Component flamegraph where only the top-most parent component re-renders when the theme state updates from button click." width="618" height="427"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Amazing! Now only the SettingsPage component re-renders when its state changes. This saves us processing time since we don't need to re-render the child components anymore.&lt;/p&gt;

&lt;h3&gt;
  
  
  Part 6: Using Our Theme
&lt;/h3&gt;

&lt;p&gt;Great, now that we have fixed our performance problem, let's try to re-add our prior functionality from above where we can use the current state of the theme to change the Button component. We naturally do this by passing the theme's value down through the Content component and into Button:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fevf5hvy9nf5dimxncbw2.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fevf5hvy9nf5dimxncbw2.gif" alt="Component flamegraph where theme is passed from top-most component to the button component. All components that touch the current theme state re-renders when it changes." width="618" height="427"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Great! We can now see the theme change in Button! Understandably, Button re-renders when this state changes. Unexpectedly though, Content also re-renders!&lt;/p&gt;

&lt;p&gt;Why is this happening? Well, going back to what was said in the previous section, &lt;code&gt;memo&lt;/code&gt; prevents re-renders only if the props are equal. With &lt;code&gt;useCallback&lt;/code&gt;, we made sure our toggle function remains stable between renders, but our theme state still changes either way.&lt;/p&gt;

&lt;p&gt;At a glance, this may feel &lt;a href="https://media.giphy.com/media/ie76dJeem4xBDcf83e/giphy.gif"&gt;inevitable&lt;/a&gt;, but we can actually improve this! You may wonder why, but if you imagine the component hierarchy being much larger, or if our Content component was very expensive to render, then avoiding re-renders can be very helpful.&lt;/p&gt;

&lt;h3&gt;
  
  
  Part 7: Replacing Component State With App State
&lt;/h3&gt;

&lt;p&gt;Alright, let's finally wrap this example up! Now that we see how difficult it is to use component state that spans across our application, we can instead try to use application state instead. This generally takes the form of using a state management library (Redux being the most popular choice), but can be as simple as using React Context.&lt;/p&gt;

&lt;p&gt;If we move our component state into app state and change our component code to connect to that app state directly (&lt;code&gt;useSelector&lt;/code&gt; in Redux, &lt;code&gt;useContext&lt;/code&gt; for React Context), we see something pretty awesome:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa4aqvaf8gr3788zd7fpj.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa4aqvaf8gr3788zd7fpj.gif" alt="Component flamegraph with app state view where update to theme state only re-renders the button component that relies on it." width="618" height="427"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you can see, we removed the state from SettingsPage and placed in into our App State. IconButton and Button can both update this state (by clicking on them) and Button reads from this state in order to show the appropriate theme to the user.&lt;/p&gt;

&lt;p&gt;We have now eliminated all component re-renders except for Button (which is to be expected since it changes when the theme changes). From a performance perspective, this is the most ideal state we can get to.&lt;/p&gt;

&lt;h2&gt;
  
  
  Maintainability
&lt;/h2&gt;

&lt;p&gt;A lot of the focus of the example above has been around creating performant React code. That said, avoiding Prop Drilling is also useful for code maintainability!&lt;/p&gt;

&lt;p&gt;When I talk about maintainability, I'm referring to one's ability to extend code, refactor it, compose it, and generally maintain it as a product evolves over time. This is a broad category, but is very useful in order to avoid foot-guns, bugs, and more over time.&lt;/p&gt;

&lt;p&gt;Returning to the code we had right before we pulled component state into app state (removing the performance improvements for clarity sake), we can see that &lt;code&gt;toggleTheme&lt;/code&gt; and &lt;code&gt;theme&lt;/code&gt; are passed down between components.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Root&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="nc"&gt;SettingsPage&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;Modal&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;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Modal&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="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="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;SettingsPage&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;theme&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;toggleTheme&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useTheme&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;IconButton&lt;/span&gt; &lt;span class="na"&gt;toggleTheme&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;toggleTheme&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;Title&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;Content&lt;/span&gt; &lt;span class="na"&gt;toggleTheme&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;toggleTheme&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;theme&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;theme&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;IconButton&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="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;toggleTheme&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;props&lt;/span&gt;

  &lt;span class="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;button&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;toggleTheme&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;Icon&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;)&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;Title&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Settings Page&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Content&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="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;toggleTheme&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;theme&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;props&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Text&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;theme&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;theme&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;toggleTheme&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;toggleTheme&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Text&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="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;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Change Theme?&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;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Button&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="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;toggleTheme&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;theme&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;props&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;button&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;toggleTheme&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;theme&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      Toggle
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The reason this code isn't maintainable is that we have tied Content to both SettingsPage and Button through a dependency (via the props). In order to use Button anywhere else, we need to make sure that its new parent also passes down the same props that Content does.&lt;/p&gt;

&lt;p&gt;To clarify this, let's use our example. What happens if we wanted to move Button to be a child of the Title component instead? Well, that change would look like the following.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;&lt;span class="p"&gt;const Root = () =&amp;gt; {
&lt;/span&gt;  return (
    &amp;lt;&amp;gt;
      &amp;lt;SettingsPage /&amp;gt;
      &amp;lt;Modal /&amp;gt;
    &amp;lt;/&amp;gt;
  )
}
&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="p"&gt;const Modal = (props) =&amp;gt; {
&lt;/span&gt;  // ...
}
&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="p"&gt;const SettingsPage = () =&amp;gt; {
&lt;/span&gt;  const [theme, toggleTheme] = useTheme()
&lt;span class="err"&gt;
&lt;/span&gt;  return (
    &amp;lt;div&amp;gt;
      &amp;lt;IconButton toggleTheme={toggleTheme} /&amp;gt;
&lt;span class="gd"&gt;-     &amp;lt;Title /&amp;gt;
-     &amp;lt;Content toggleTheme={toggleTheme} theme={theme} /&amp;gt;
&lt;/span&gt;&lt;span class="gi"&gt;+     &amp;lt;Title toggleTheme={toggleTheme} theme={theme} /&amp;gt;
+     &amp;lt;Content /&amp;gt;
&lt;/span&gt;    &amp;lt;/div&amp;gt;
  )
}
&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="p"&gt;const IconButton = (props) =&amp;gt; {
&lt;/span&gt;  const { toggleTheme } = props
&lt;span class="err"&gt;
&lt;/span&gt;  return (
    &amp;lt;button onClick={toggleTheme}&amp;gt;
      &amp;lt;Icon /&amp;gt;
    &amp;lt;/button&amp;gt;
  )
}
&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="p"&gt;const Title = (props) =&amp;gt; {
&lt;/span&gt;&lt;span class="gi"&gt;+ const { toggleTheme, theme } = props
+
&lt;/span&gt;  return (
    &amp;lt;div&amp;gt;
      &amp;lt;h1&amp;gt;Settings Page&amp;lt;/h1&amp;gt;
&lt;span class="gi"&gt;+     &amp;lt;Button theme={theme} toggleTheme={toggleTheme} /&amp;gt;
&lt;/span&gt;    &amp;lt;/div&amp;gt;
  )
}
&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="p"&gt;const Content = (props) =&amp;gt; {
&lt;/span&gt;&lt;span class="gd"&gt;- const { toggleTheme, theme } = props
&lt;/span&gt;  return (
    &amp;lt;div&amp;gt;
      &amp;lt;Text /&amp;gt;
&lt;span class="gd"&gt;-     &amp;lt;Button theme={theme} toggleTheme={toggleTheme} /&amp;gt;
&lt;/span&gt;    &amp;lt;/div&amp;gt;
  )
}
&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="p"&gt;const Text = (props) =&amp;gt; {
&lt;/span&gt;  return &amp;lt;p&amp;gt;Change Theme?&amp;lt;/p&amp;gt;
}
&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="p"&gt;const Button = (props) =&amp;gt; {
&lt;/span&gt;  const { toggleTheme, theme } = props
&lt;span class="err"&gt;
&lt;/span&gt;  return (
    &amp;lt;button onClick={toggleTheme} className={theme}&amp;gt;
      Toggle
    &amp;lt;/button&amp;gt;
  )
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As we can see from the code diff, we had to manage a few props and make sure they get passed through properly. In this example, it's not too difficult, but imagine if we needed to update several intermediate components in order to get things to work. Things can quickly get more complicated!&lt;/p&gt;

&lt;p&gt;Now let's imagine we wanted to move Button to a completely different part of the component hierarchy. We would need to move the component state so that it exists within an ancestor component for all of its instances.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;&lt;span class="p"&gt;const Root = () =&amp;gt; {
&lt;/span&gt;&lt;span class="gi"&gt;+ const [theme, toggleTheme] = useTheme()
+
&lt;/span&gt;  return (
    &amp;lt;&amp;gt;
&lt;span class="gd"&gt;-     &amp;lt;SettingsPage /&amp;gt;
-     &amp;lt;Modal /&amp;gt;
&lt;/span&gt;&lt;span class="gi"&gt;+     &amp;lt;SettingsPage toggleTheme={toggleTheme} theme={theme} /&amp;gt;
+     &amp;lt;Modal theme={theme} /&amp;gt;
&lt;/span&gt;    &amp;lt;/&amp;gt;
  )
}
&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="p"&gt;const Modal = (props) =&amp;gt; {
&lt;/span&gt;  // ...
}
&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="p"&gt;const SettingsPage = () =&amp;gt; {
&lt;/span&gt;&lt;span class="gd"&gt;- const [theme, toggleTheme] = useTheme()
&lt;/span&gt;&lt;span class="gi"&gt;+ const { toggleTheme, theme } = props
&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;  return (
    &amp;lt;div&amp;gt;
      &amp;lt;IconButton toggleTheme={toggleTheme} /&amp;gt;
      &amp;lt;Title /&amp;gt;
      &amp;lt;Content toggleTheme={toggleTheme} theme={theme} /&amp;gt;
    &amp;lt;/div&amp;gt;
  )
}
&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="p"&gt;const IconButton = (props) =&amp;gt; {
&lt;/span&gt;  const { toggleTheme } = props
&lt;span class="err"&gt;
&lt;/span&gt;  return (
    &amp;lt;button onClick={toggleTheme}&amp;gt;
      &amp;lt;Icon /&amp;gt;
    &amp;lt;/button&amp;gt;
  )
}
&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="p"&gt;const Title = (props) =&amp;gt; {
&lt;/span&gt;  return (
    &amp;lt;div&amp;gt;
      &amp;lt;h1&amp;gt;Settings Page&amp;lt;/h1&amp;gt;
    &amp;lt;/div&amp;gt;
  )
}
&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="p"&gt;const Content = (props) =&amp;gt; {
&lt;/span&gt;  const { toggleTheme, theme } = props
&lt;span class="err"&gt;
&lt;/span&gt;  return (
    &amp;lt;div&amp;gt;
      &amp;lt;Text /&amp;gt;
      &amp;lt;Button theme={theme} toggleTheme={toggleTheme} /&amp;gt;
    &amp;lt;/div&amp;gt;
  )
}
&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="p"&gt;const Text = (props) =&amp;gt; {
&lt;/span&gt;  return &amp;lt;p&amp;gt;Change Theme?&amp;lt;/p&amp;gt;
}
&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="p"&gt;const Button = (props) =&amp;gt; {
&lt;/span&gt;  const { toggleTheme, theme } = props
&lt;span class="err"&gt;
&lt;/span&gt;  return (
    &amp;lt;button onClick={toggleTheme} className={theme}&amp;gt;
      Toggle
    &amp;lt;/button&amp;gt;
  )
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This example is basic, but in real-world scenarios, this potentially entails moving it up several layers of components. As we would expect, this can quickly get out of hand and it is much more difficult to maintain as the codebase changes. We've now modified several different components unrelated to the feature we were working on (not fun for code review) and introduced an increased risk of accidentally breaking something (not fun for on-call).&lt;/p&gt;

&lt;p&gt;Now, what does it look like to change this code to use app state instead? Quite simply, it just takes moving the component in the right place. We've fully encapsulated the logic associated with the component to itself so that we're not polluting the rest of our application in the process.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;&lt;span class="p"&gt;const Root = () =&amp;gt; {
&lt;/span&gt;  return (
    &amp;lt;&amp;gt;
      &amp;lt;SettingsPage /&amp;gt;
      &amp;lt;Modal /&amp;gt;
    &amp;lt;/&amp;gt;
  )
}
&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="p"&gt;const Modal = (props) =&amp;gt; {
&lt;/span&gt;&lt;span class="gi"&gt;+ const theme = useSelector(themeSelector)
&lt;/span&gt;  // ...
}
&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="p"&gt;const SettingsPage = () =&amp;gt; {
&lt;/span&gt;&lt;span class="gd"&gt;- const [theme, toggleTheme] = useTheme()
&lt;/span&gt;  return (
    &amp;lt;div&amp;gt;
&lt;span class="gd"&gt;-     &amp;lt;IconButton toggleTheme={toggleTheme} /&amp;gt;
&lt;/span&gt;&lt;span class="gi"&gt;+     &amp;lt;IconButton /&amp;gt;
&lt;/span&gt;      &amp;lt;Title /&amp;gt;
&lt;span class="gd"&gt;-     &amp;lt;Content toggleTheme={toggleTheme} theme={theme} /&amp;gt;
&lt;/span&gt;&lt;span class="gi"&gt;+     &amp;lt;Content /&amp;gt;
&lt;/span&gt;    &amp;lt;/div&amp;gt;
  )
}
&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="p"&gt;const IconButton = (props) =&amp;gt; {
&lt;/span&gt;&lt;span class="gd"&gt;- const { toggleTheme } = props
&lt;/span&gt;&lt;span class="gi"&gt;+ const dispatch = useDispatch()
+ const toggleTheme = () =&amp;gt; dispatch(toggleThemeAction)
&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;  return (
    &amp;lt;button onClick={toggleTheme}&amp;gt;
      &amp;lt;Icon /&amp;gt;
    &amp;lt;/button&amp;gt;
  )
}
&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="p"&gt;const Title = (props) =&amp;gt; {
&lt;/span&gt;  return (
    &amp;lt;div&amp;gt;
      &amp;lt;h1&amp;gt;Settings Page&amp;lt;/h1&amp;gt;
    &amp;lt;/div&amp;gt;
  )
}
&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="p"&gt;const Content = (props) =&amp;gt; {
&lt;/span&gt;&lt;span class="gd"&gt;- const { toggleTheme, theme } = props
&lt;/span&gt;  return (
    &amp;lt;div&amp;gt;
      &amp;lt;Text /&amp;gt;
&lt;span class="gd"&gt;-     &amp;lt;Button theme={theme} toggleTheme={toggleTheme} /&amp;gt;
&lt;/span&gt;&lt;span class="gi"&gt;+     &amp;lt;Button /&amp;gt;
&lt;/span&gt;    &amp;lt;/div&amp;gt;
  )
}
&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="p"&gt;const Text = (props) =&amp;gt; {
&lt;/span&gt;  return &amp;lt;p&amp;gt;Change Theme?&amp;lt;/p&amp;gt;
}
&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="p"&gt;const Button = (props) =&amp;gt; {
&lt;/span&gt;&lt;span class="gd"&gt;- const { toggleTheme, theme } = props
&lt;/span&gt;&lt;span class="gi"&gt;+ const dispatch = useDispatch()
+ const theme = useSelector(themeSelector)
+ const toggleTheme = () =&amp;gt; dispatch(toggleThemeAction)
&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;  return (
    &amp;lt;button onClick={toggleTheme} className={theme}&amp;gt;
      Toggle
    &amp;lt;/button&amp;gt;
  )
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, when we want to move the Button to be a child of the Title component, it's much more simple:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;&lt;span class="p"&gt;const Root = () =&amp;gt; {
&lt;/span&gt;  return (
    &amp;lt;&amp;gt;
      &amp;lt;SettingsPage /&amp;gt;
      &amp;lt;Modal /&amp;gt;
    &amp;lt;/&amp;gt;
  )
}
&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="p"&gt;const Modal = (props) =&amp;gt; {
&lt;/span&gt;  const theme = useSelector(themeSelector)
  // ...
}
&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="p"&gt;const SettingsPage = () =&amp;gt; {
&lt;/span&gt;  return (
    &amp;lt;div&amp;gt;
      &amp;lt;IconButton /&amp;gt;
      &amp;lt;Title /&amp;gt;
      &amp;lt;Content /&amp;gt;
    &amp;lt;/div&amp;gt;
  )
}
&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="p"&gt;const IconButton = (props) =&amp;gt; {
&lt;/span&gt;  const dispatch = useDispatch()
  const toggleTheme = () =&amp;gt; dispatch(toggleThemeAction)
&lt;span class="err"&gt;
&lt;/span&gt;  return (
    &amp;lt;button onClick={toggleTheme}&amp;gt;
      &amp;lt;Icon /&amp;gt;
    &amp;lt;/button&amp;gt;
  )
}
&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="p"&gt;const Title = (props) =&amp;gt; {
&lt;/span&gt;  return (
    &amp;lt;div&amp;gt;
      &amp;lt;h1&amp;gt;Settings Page&amp;lt;/h1&amp;gt;
&lt;span class="gi"&gt;+     &amp;lt;Button /&amp;gt;
&lt;/span&gt;    &amp;lt;/div&amp;gt;
  )
}
&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="p"&gt;const Content = (props) =&amp;gt; {
&lt;/span&gt;  return (
    &amp;lt;div&amp;gt;
      &amp;lt;Text /&amp;gt;
&lt;span class="gd"&gt;-     &amp;lt;Button /&amp;gt;
&lt;/span&gt;    &amp;lt;/div&amp;gt;
  )
}
&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="p"&gt;const Text = (props) =&amp;gt; {
&lt;/span&gt;  return &amp;lt;p&amp;gt;Change Theme?&amp;lt;/p&amp;gt;
}
&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="p"&gt;const Button = (props) =&amp;gt; {
&lt;/span&gt;  const dispatch = useDispatch()
  const theme = useSelector(themeSelector)
  const toggleTheme = () =&amp;gt; dispatch(toggleThemeAction)
&lt;span class="err"&gt;
&lt;/span&gt;  return (
    &amp;lt;button onClick={toggleTheme} className={theme}&amp;gt;
      Toggle
    &amp;lt;/button&amp;gt;
  )
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A lot more simple, yeah? This code is more maintainable which allows us to easily extend, refactor, and compose as we build new features. This is a huge win for developer velocity and developer experience!&lt;/p&gt;

&lt;h2&gt;
  
  
  How to Create App State
&lt;/h2&gt;

&lt;p&gt;Now, if you're new to React, you may be wondering how to create app state in your application. The best way to do so is to use a state management dependency to help out! The most popular option today is &lt;a href="https://redux.js.org/"&gt;Redux&lt;/a&gt; and I'd encouraged you to use &lt;a href="https://redux-toolkit.js.org/"&gt;Redux Toolkit&lt;/a&gt; if you choose to go this route.&lt;/p&gt;

&lt;p&gt;If your needs are simple, you can also just use React's builtin &lt;a href="https://react.dev/learn/passing-data-deeply-with-context"&gt;context&lt;/a&gt;. This is a part of React and doesn't need any additional dependencies to work. That said, there are similar performance issues from above that can occur when using objects and functions for the value of the context (due to reference equality checks).&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping Up: Should I Ever Use Prop Drilling?
&lt;/h2&gt;

&lt;p&gt;Now that we have reached the end of the article, you may be thinking that all forms of Prop Drilling are bad. This is where I tell you that there is time and place for everything. Prop Drilling can sometimes simplify code and definitely makes more sense in certain cases (like generic forms / components).&lt;/p&gt;

&lt;p&gt;It's useful to recognize that React is &lt;em&gt;very&lt;/em&gt; fast at re-rendering components, so it's important to profile your application to see if there are any performance issues before changing any code.&lt;/p&gt;

&lt;p&gt;That said, I hope this has helped you better understand Prop Drilling and how it can impact your app's performance and maintainability! Cheers!&lt;/p&gt;

</description>
      <category>react</category>
      <category>javascript</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Opaque / Branded Types in Typescript</title>
      <dc:creator>Tiago Ferreira</dc:creator>
      <pubDate>Wed, 28 Sep 2022 15:12:53 +0000</pubDate>
      <link>https://dev.to/tiagof/opaque-branded-types-in-typescript-59fd</link>
      <guid>https://dev.to/tiagof/opaque-branded-types-in-typescript-59fd</guid>
      <description>&lt;p&gt;Typescript has amassed quite the following as one of the top ten most popular programming languages over the last several years. And for good reason! It has greatly accelerated development by providing compile-time guarantees that supports a greater development velocity while maintaining a high bar of quality.&lt;/p&gt;

&lt;p&gt;As a quick overview, Typescript provides compile-time type checking in order to prevent common datatype bugs (among other things 😉). It has several native types defined that you can annotate variables with. These range from &lt;code&gt;number&lt;/code&gt;, to &lt;code&gt;string&lt;/code&gt;, to array/tuple definitions, and more. It even supports more complex types with unions, intersections, and string literals that can allow for incredibly expressive types to reflect the data that you are working with.&lt;/p&gt;

&lt;p&gt;However, &lt;code&gt;number&lt;/code&gt; or &lt;code&gt;string&lt;/code&gt; isn't always specific enough. Sometimes our code specifically needs a value between 0-1 or only a valid email should be used.&lt;/p&gt;

&lt;h1&gt;
  
  
  What's wrong with just using the general type?
&lt;/h1&gt;

&lt;p&gt;Although more general types like &lt;code&gt;number&lt;/code&gt; or &lt;code&gt;string&lt;/code&gt; can suffice in terms of general compile-time checks, they fail to provide checks for more nuanced cases. Take for example a function that requires a percentage as an input:&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="cm"&gt;/**
* Sets the alpha value for an image.
* @param percentage - a number between 0 and 1
*/&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;setAlpha&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;percentage&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="p"&gt;...&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this case, we want a &lt;code&gt;number&lt;/code&gt; type passed in, but specifically a number between 0 and 1. However, this can cause several potential problems:&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="nf"&gt;setAlpha&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// Correct&lt;/span&gt;
&lt;span class="nf"&gt;setAlpha&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mf"&gt;0.5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// Runtime Error: Invalid Percentage - Typescript doesn't catch this&lt;/span&gt;
&lt;span class="nf"&gt;setAlpha&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;2.3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// Runtime Error: Invalid Percentage - Typescript doesn't catch this&lt;/span&gt;
&lt;span class="nf"&gt;setAlpha&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;abc&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// Build Error: string instead of number - Typescript does catch this&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In classical Javascript fashion, one would usually say "add a runtime check." We could do that, but before Typescript, we would also create runtime checks to confirm that data was a &lt;code&gt;number&lt;/code&gt; in the first place.&lt;/p&gt;

&lt;p&gt;What if we could do the same for this case? It would make sense to try to add type checking for percentages as well since that would catch the types of errors mentioned above during compile-time.&lt;/p&gt;

&lt;p&gt;Ideally, we want to just specify that our function only accepts a percentage as its input:&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;function&lt;/span&gt; &lt;span class="nf"&gt;setAlpha&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;percentage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Percentage&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But how do we create a &lt;code&gt;Percentage&lt;/code&gt; type?&lt;/p&gt;

&lt;h1&gt;
  
  
  Defining a New Type
&lt;/h1&gt;

&lt;p&gt;One may think of aliasing as creating a new type (i.e. &lt;code&gt;type Percentage = number&lt;/code&gt;), but that merely gives a new name to an existing type. The problem with an aliased type is that it's purely descriptive rather than a functional change (i.e. it's interchangeable with the original type).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;value&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="mf"&gt;1.5&lt;/span&gt; &lt;span class="c1"&gt;// Invalid `Percentage`&lt;/span&gt;
&lt;span class="nf"&gt;setAlpha&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="c1"&gt;// Works even though setAlpha expects `Percentage`&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What we want to do is to create a new opaque type (also known as a tagged / branded type). Other type systems, like Flow, &lt;a href="https://flow.org/en/docs/types/opaque-types/"&gt;already have this ability built in&lt;/a&gt;, but Typescript does not.&lt;/p&gt;

&lt;p&gt;Instead, to achieve something similar, we can 'tag' the type to indicate that it's different from the base type (in this case a &lt;code&gt;number&lt;/code&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Percentage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;_tag&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;percentage&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By intersecting &lt;code&gt;number&lt;/code&gt; with a unique object, we prevent the type that we have defined from accepting any value that satisfies the base type. In this case, a generic &lt;code&gt;number&lt;/code&gt; would not be accepted in functions that expect a &lt;code&gt;Percentage&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;value&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="mf"&gt;0.5&lt;/span&gt; &lt;span class="c1"&gt;// Valid `Percentage`, but typed as a general `number`&lt;/span&gt;
&lt;span class="nf"&gt;setAlpha&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="c1"&gt;// Build Error: number instead of Percentage&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://www.typescriptlang.org/play?#code/C4TwDgpgBAChBOBjCA7YBDA5hAjFAvFCgK4C2ARggLABQoksCyaWEATAUWZfFAGRQA3lAD6GTAC4oAIkhJU4iNKgBfWrQBmxFImABLAPYooAZwjAAggBswAC3QAGABRypJCggCUQqAHoAVAB0wf6+qprauobGZpY29jguCFJw8izYON7CAcGBoeE0Wjr6Rqbm1nbobEnwKUwKrGxZfkEhYWo0tIhGJsBQAG7oVg5u3AicDoEArF09fYNWOHVpiniEkzM0vmEA6tAoEBAAJlDABlDd9ae20PTQJno60AAGG89Q5CBQRxAa6MRWPp6EyncDHKDoEHPdw8Z6zFC9AZDDjraYQkGpZiKNjqLZhaxWUGQEEGDRQZ4Ld7oeDQdCIZBgYDgh5Pa4QEAAchpEKshPgBgMTJOjzZUDA1PQpA5ILu5JhCDhNFiFXszgWDk8tGV8UcTgWmS15R1auRms6eKgBKJEBJZIpQyp3LpDKFUA0Bl4wBupkl0BpkNKkPJ2sqDneLOQPL0kJtEO5wH9rqsegA1rdvR69JhHkNrYa4pVEuqzSGEnqhgalUbC+WrE1cdsoAAhQW2Wzk9VUlAne2LR23RPgoPQsbwd4Ad1sekQ7eBUEe3VI4v05Cs0HHei9otIHvukEQeg00-JmIa2DYitLVVrGr8YQAovB+bwALRcDy8OcoQXoh6YFDoKutznKe6QQPmKrXvq3iNo+z5QG+8qfiC359JCf4AUBpwgfUYEQTq1QLE0QA"&gt;&lt;em&gt;Typescript playground example&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;However, you may now wonder how do you define a variable as a &lt;code&gt;Percentage&lt;/code&gt; type. The simple method is to explicitly cast the value with the &lt;code&gt;as&lt;/code&gt; keyword:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.5&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;Percentage&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The downside is that this is only reasonable for constants specified at compile-time, what about runtime values?&lt;/p&gt;

&lt;h2&gt;
  
  
  Conversion Functions
&lt;/h2&gt;

&lt;p&gt;We can solve this issue by creating runtime checks as functions that refine types appropriately:&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;function&lt;/span&gt; &lt;span class="nf"&gt;isPercentage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;input&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="nx"&gt;input&lt;/span&gt; &lt;span class="k"&gt;is&lt;/span&gt; &lt;span class="nx"&gt;Percentage&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;input&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;input&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;is&lt;/code&gt; keyword indicates to Typescript that if this function returns &lt;code&gt;true&lt;/code&gt;, then the input is a &lt;code&gt;Percentage&lt;/code&gt; type (&lt;a href="https://www.typescriptlang.org/docs/handbook/2/narrowing.html#using-type-predicates"&gt;known as a type predicate&lt;/a&gt;). You can then use this runtime check function to create a set of conversion functions:&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;function&lt;/span&gt; &lt;span class="nf"&gt;toPercentage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;input&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="nx"&gt;Percentage&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;return&lt;/span&gt; &lt;span class="nf"&gt;isPercentage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;input&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;fromPercentage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Percentage&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="nx"&gt;input&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can now use these functions throughout your codebase if you need runtime checks for data. Then you'll get the benefits of compile-time checks for functions that you defined that require these specific values.&lt;/p&gt;

&lt;h1&gt;
  
  
  Does this actually help?
&lt;/h1&gt;

&lt;p&gt;For smaller applications, this level of type granularity is likely not particularly useful. However, as an application grows in complexity, compile-time type checking can seriously help prevent bugs related from misunderstanding the intention behind code (imagine looking at your own code from 6 months ago...).&lt;/p&gt;

&lt;p&gt;Let's take our &lt;code&gt;setAlpha&lt;/code&gt; example from above:&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;function&lt;/span&gt; &lt;span class="nf"&gt;setAlpha&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;percentage&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="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 may seem obvious from the naming that this should be a value from 0 to 1, but consider potentially a value between 0% and 100%. I can understand someone thinking that &lt;code&gt;setAlpha(20)&lt;/code&gt; is a reasonable use of the function. Only at runtime will we realize that something is wrong.&lt;/p&gt;

&lt;p&gt;To further this problem, as your application gets even more complicated, you may not immediately notice the error during runtime. Only at a later time when you've forgotten about writing this could the issue pop up again unexpectedly.&lt;/p&gt;

&lt;p&gt;By changing the type of the percentage parameter, we can enforce better compile-time type-checking in order to catch these issues earlier on. Now if we defined &lt;code&gt;setAlpha&lt;/code&gt; with the more refined type:&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;function&lt;/span&gt; &lt;span class="nf"&gt;setAlpha&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;percentage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Percentage&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then we can get appropriate errors at compile-time when you try to pass in a generic number into the function. It will require either an explicit casting, or an assertion using our &lt;code&gt;isPercentage&lt;/code&gt; function in order to make sure the type is correct.&lt;/p&gt;

&lt;p&gt;This has the great benefit of allowing you to use the runtime check once for user input, and then have a compile-time guarantee for the data as it's passed through the system. Like so:&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;// User input is a string from a text field&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;percentage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;parseFloat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userInput&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// type: number&lt;/span&gt;
&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nf"&gt;isPercentage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;percentage&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// percentage is not of type `Percentage` and is therefore&lt;/span&gt;
  &lt;span class="c1"&gt;// and invalid input. Handle appropriate error code here.&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;// percentage is type `Percentage` and has compile-time checking&lt;/span&gt;
&lt;span class="c1"&gt;// to confirm that it works with the `setAlpha` function&lt;/span&gt;
&lt;span class="nf"&gt;setAlpha&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;percentage&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you were to take the same example, and remove the check for percentage's type, then you'd get a compile-time error from Typescript regarding the use of &lt;code&gt;number&lt;/code&gt; for a parameter that requires a &lt;code&gt;Percentage&lt;/code&gt; (&lt;a href="https://www.typescriptlang.org/play?ssl=15&amp;amp;ssc=42&amp;amp;pln=15&amp;amp;pc=58#code/PTAEBEFMDMEsDsEHNQBcAWlQAVICcBjSeVAQyS1QE8AHLU+AE1FNDwFcTYBbLAzAgGtQ0APZ5QsVAFgAUNTo58REuSwBeUPHbcARvlAAyUAG9QAfTJIAXKABEdQsSuQ7oAL5zonAqlij4SQBnXCdVCgAKBBp2VFttPXwASlto2OClMJdTOVA2SFR2PEC01FAAPk0ABiNjUtAAHk0ARjlPWTkQCBgEZFAggoBBABsadFZveF9-QNIglkDIAA9SbhphrFFoFlB2AdAtzJUXLx8-AP6h0fGIx2O1W1D7iiTTds6wAFUBiXqAd1E7GGzAo8HwpGGwyooAIol4IjwcJ2qGWqDgkGBBwkQThBXQyDksPgQTKe3wAEl4DEypo7AAWACsADoqs07HIPqAALQ80AAURWaw2oGatgAcqIYQJhGIJE9nGpuTyObIiSTQHcFRRmqBNDRSHgBgAxYaiUioCJkvCU6mvLoKSDxHT6PByAaoEZjUi3ZRayDNO1gPl4RESLlaZ0GWDzeCiMpzIKwJDwUi6YWoSXy8KQFVdHnhgWrdZYABMtgAwtK+rKjn6lVyVWqyprsyXdRqDcbTebLT8bbFA2haI6I4lXbJYNsIgBCaNZlw+rJqEtJV4mOQASC6Ley0a0cYO2wdoAABvO1CfNxhEX8tJBb8HQxE7BL46AAG4Q9hYfSoP6QYhQBqBhmDZJI2lzMAd0VPdjzPX1s0vWR3U9G5oIoFcgA"&gt;Typescript playground example&lt;/a&gt;).&lt;/p&gt;

&lt;h1&gt;
  
  
  Opaque Type Variations
&lt;/h1&gt;

&lt;p&gt;Now that we've hopefully determined that this is generally a good idea, let's take it up a notch with some additional variations of opaque types. &lt;a href="https://github.com/microsoft/TypeScript/issues/4895#issuecomment-425132582"&gt;All credit to &lt;em&gt;ProdigySim&lt;/em&gt; on Github for figuring this out&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;For the simplification of defining opaqueness, let's define a simple helper type:&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;Tag&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;_tag&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;T&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Weak Opaque Type
&lt;/h2&gt;

&lt;p&gt;This is the opaque type we've been talking about here with &lt;code&gt;Percentage&lt;/code&gt;. It's uses the same definition as above (though cleaned up using the helper type this time):&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;Percentage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;Tag&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;percentage&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This weak opaque type is useful because it can be downcasted into the base type of &lt;code&gt;number&lt;/code&gt; in cases like passing it into a function while protecting from the incorrect use of &lt;code&gt;number&lt;/code&gt; in cases where we need a &lt;code&gt;Percentage&lt;/code&gt;. For example:&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;function&lt;/span&gt; &lt;span class="nf"&gt;add&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="kr"&gt;number&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;setAlpha&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Percentage&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;num&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.5&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;per&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.5&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;Percentage&lt;/span&gt;

&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;num&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// Works: number = number&lt;/span&gt;
&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;per&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// Works: Percentage downcasts to number&lt;/span&gt;

&lt;span class="nf"&gt;setAlpha&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;num&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// Error: Cannot use a number when it expects a Percentage&lt;/span&gt;
&lt;span class="nf"&gt;setAlpha&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;per&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// Works: Percentage = Percentage&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Strong Opaque Type
&lt;/h2&gt;

&lt;p&gt;A strong opaque type is defined a little bit differently:&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;Percentage&lt;/span&gt; &lt;span class="o"&gt;=&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;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;Tag&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;percentage&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nx"&gt;Tag&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;percentage&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Key difference is the addition of &lt;code&gt;| Tag&amp;lt;"percentage"&amp;gt;&lt;/code&gt; at the end.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Strong opaque types have the additional restriction of requiring explicit casting in order to be used as their base types (&lt;code&gt;number&lt;/code&gt; in this example). This means that we wouldn't be able to pass a &lt;code&gt;Percentage&lt;/code&gt; into the &lt;code&gt;add&lt;/code&gt; function above without explicitly casting it first:&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;function&lt;/span&gt; &lt;span class="nf"&gt;add&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="kr"&gt;number&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;per&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.5&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;Percentage&lt;/span&gt;

&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;per&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// Error: Percentage is incompatible with number&lt;/span&gt;
&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;per&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// Works: Percentage explicitly casted to number&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This can be useful in cases where you don't accidentally want to use the more specific type for more general cases without a clear exception being made via explicit casting.&lt;/p&gt;

&lt;h2&gt;
  
  
  Super Opaque Type
&lt;/h2&gt;

&lt;p&gt;A super opaque type has the simplest definition of them all:&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;Percentage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Tag&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;percentage&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Super opaque types have the most stringent typings and cannot be implicitly or explicitly casted to their base types. This means that we need to cast the type to &lt;code&gt;any&lt;/code&gt; first before we can cast it to the base type for use:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;add&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="kr"&gt;number&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;per&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.5&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;Percentage&lt;/span&gt;

&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;per&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// Error: Percentage is incompatible with number&lt;/span&gt;
&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;per&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// Error: Percentage does not sufficiently overlap number&lt;/span&gt;
&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;per&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// Works: Ignoring the inherent types to allow Percentage to be used in place of number&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is useful for cases where you are truly making a new type that is unrelated any base type. This is like comparing &lt;code&gt;number&lt;/code&gt; to &lt;code&gt;string&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Note: Super Opaque Type boils down to just typing the data as an object with a special key, thus this can cause unexpected edge-cases when functions accept any object.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Defining Opaque Helper Types
&lt;/h2&gt;

&lt;p&gt;From these different opaque types, we can define some simple helper types that reflect the different ways we can define an opaque type within Typescript:&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;Tag&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;_tag&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;T&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;WeakOpaqueType&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;BaseType&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;BaseType&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;Tag&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;StrongOpaqueType&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;BaseType&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;BaseType&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;Tag&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&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;|&lt;/span&gt; &lt;span class="nx"&gt;Tag&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;SuperOpaqueType&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Tag&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can copy and use these helper types within your own code in order to begin defining your own custom types. Good luck!&lt;/p&gt;

&lt;h1&gt;
  
  
  3rd Party Libraries
&lt;/h1&gt;

&lt;p&gt;Now you may be wondering if there are any prebuilt solutions for you to use within your code. I'm happy to say that there is! One notable library I've come across is &lt;a href="https://github.com/sveseme/taghiro"&gt;taghiro&lt;/a&gt;. It defines several numeric and string types (like UUID, ascii, and regex) with corresponding validation functions to allow for assertions within your code that refines the types appropriately.&lt;/p&gt;

&lt;p&gt;Something to note from the library is that all of the exported types are super opaque types while all of the assertions refine into weak opaque types.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Note: I’m not connected to development of &lt;code&gt;taghiro&lt;/code&gt;. Use at your own risk.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>typescript</category>
      <category>webdev</category>
      <category>programming</category>
    </item>
    <item>
      <title>React Re-Mounting vs. Re-Rendering</title>
      <dc:creator>Tiago Ferreira</dc:creator>
      <pubDate>Fri, 06 Nov 2020 17:35:00 +0000</pubDate>
      <link>https://dev.to/tiagof/react-re-mounting-vs-re-rendering-lnh</link>
      <guid>https://dev.to/tiagof/react-re-mounting-vs-re-rendering-lnh</guid>
      <description>&lt;p&gt;What would the following lines of code do when React is rendering a component? Would they cause &lt;code&gt;Counter&lt;/code&gt; to get re-mounted or re-rendered?&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;// 'name' is a variable that is either "A" or "B"&lt;/span&gt;

&lt;span class="c1"&gt;// Passing in the name as a prop&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Counter&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&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;gt;&lt;/span&gt;

&lt;span class="c1"&gt;// Ternary expression with two written cases of Counter&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;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;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Counter&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"A"&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;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Counter&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"B"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Ternary expression with a Counter and a different element&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;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;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Counter&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"A"&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;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;EMPTY&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you said that the first two will re-render &lt;code&gt;Counter&lt;/code&gt; while the third will cause a re-mount, then you are correct! You can verify this for yourself with this &lt;a href="https://codesandbox.io/s/cocky-water-7rz6g?file=/src/App.js" rel="noopener noreferrer"&gt;codesandbox link&lt;/a&gt;. The "Basic" section shows all three cases mentioned above.&lt;/p&gt;

&lt;h1&gt;
  
  
  The Basic Case
&lt;/h1&gt;

&lt;p&gt;To provide some context on &lt;code&gt;Counter&lt;/code&gt;, it's a simple component that holds an internal count (with the &lt;code&gt;useState&lt;/code&gt; hook) for the number of times it has been pressed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Counter&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setCount&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;increment&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setCount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;increment&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;props&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;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&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;count&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&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;From this component, the most basic use case would simply be passing in the name as a prop 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;// Passing in the name as a prop&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Counter&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&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;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is probably the most common and intuitive case. When React receives new props for a component, it will re-render the component. This results in any internal &lt;code&gt;useState&lt;/code&gt; hooks maintaining their internal data – which in our case means the count remains the same.&lt;/p&gt;

&lt;h1&gt;
  
  
  The Unintuitive Re-Render Case
&lt;/h1&gt;

&lt;p&gt;The next case is less intuitive:&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;// Ternary expression with two written cases of Counter&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;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;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Counter&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"A"&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;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Counter&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"B"&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;At first glance, there appears to be two separate components that are being used in order to render counters; each counter associated with a different name. This could lead one to believe that both counters will go through a mount and unmount process when switching between them. However, that is not the case.&lt;/p&gt;

&lt;p&gt;Since these are both the same component type, React actually sees this as identical to the first case. Under the hood, React uses a Virtual DOM reconciler based on a &lt;em&gt;&lt;a href="https://giamir.com/what-is-react-fiber" rel="noopener noreferrer"&gt;Fiber Architecture&lt;/a&gt;&lt;/em&gt; that determines how to update components (re-rendering, mounting, unmounting, etc). This reconciler uses the type of the component and the props in order to determine what lifecycle operations to take. In this case, both branches of the ternary use the same component type, but different props. This causes the reconciler to re-render the component and simply change the props passed in.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why is this important?
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"Of course this case is the same! The code is functionally equivalent! Why are you telling me this?"&lt;/em&gt;&lt;br&gt;
- &lt;em&gt;someone who's too impatient to continue reading&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Consider an application with tabs. You may have the same components that stay within the same locations across tabs. Since the components line up within the Virtual DOM hierarchy between tab transitions, this can unexpectedly cause the same re-rendering behavior to occur.&lt;/p&gt;

&lt;h1&gt;
  
  
  The Intuitive Re-Mount Case
&lt;/h1&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Ternary expression with a Counter and a different element&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;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;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Counter&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"A"&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;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;EMPTY&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Alright, back to the intuitive. To tie it all together, the reason why this case re-mounts is quite simply due to the change in component types. On the left branch we have a &lt;code&gt;Counter&lt;/code&gt; component while on the right branch we have a &lt;code&gt;p&lt;/code&gt; element. As mentioned above, React's reconciler uses these component types in order to determine what operations to take. Since the types are different when you switch branches, it will unmount the component that was mounted and mount the component that was unmounted.&lt;/p&gt;

&lt;p&gt;This unmounting process throws away any data saved within the component's state. Likewise, the mounting process causes component state to initialize with default values (e.g. the initial value passed into a &lt;code&gt;useState&lt;/code&gt; hook). This is what causes our count state to reset to &lt;code&gt;0&lt;/code&gt; whenever switching between branches.&lt;/p&gt;

&lt;h1&gt;
  
  
  What do I do with this information?
&lt;/h1&gt;

&lt;p&gt;Well, there are a few real world cases where you may want to specifically have re-rendering or re-mounting behavior. Let's continue to use the &lt;code&gt;Counter&lt;/code&gt; component and build upon it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Replicating Re-Mounting
&lt;/h2&gt;

&lt;p&gt;Let's say that we have a web app that allows you to manage multiple users. Each of these users has a &lt;code&gt;Counter&lt;/code&gt; component and allows you to save their respective counts. You may write the user component like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;User&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;
  &lt;span class="k"&gt;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;Counter&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&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;name&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;And with this &lt;code&gt;User&lt;/code&gt; component, you set up a tabs component that shows one user at a time.&lt;/p&gt;

&lt;p&gt;The problem that will occur here is that the &lt;code&gt;Counter&lt;/code&gt; component's state won't reset between users. This means that when you switch between the tabs, the count will stay the same and you may accidentally save the wrong count for a given user. Extrapolating this out from a simple counter, your app may cause you to save sensitive data to the wrong user – which is a severe breach of security.&lt;/p&gt;

&lt;p&gt;So, "how do I fix this?"&lt;/p&gt;

&lt;p&gt;Well, the solution is a &lt;code&gt;useEffect&lt;/code&gt; hook. We want to listen for changes to props within the &lt;code&gt;Counter&lt;/code&gt; component in order to reset the state manually ourselves:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Counter&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setCount&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;increment&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setCount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="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;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="nf"&gt;setCount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;props&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;All that we've added here is a simple &lt;code&gt;useEffect&lt;/code&gt; hook that runs every time the &lt;code&gt;name&lt;/code&gt; prop changes for the component. This causes the internal &lt;code&gt;count&lt;/code&gt; to get reset and our 'sensitive' data to avoid leaking into other users.&lt;/p&gt;

&lt;p&gt;You can confirm this for yourself by heading to the &lt;a href="https://codesandbox.io/s/cocky-water-7rz6g" rel="noopener noreferrer"&gt;same codesandbox link&lt;/a&gt; as before and checking out the "Replicating Re-Mounting" section. Although it is defined the exact same way as the first case from the "Basic" section, it acts most similarly to the third case with its re-mounting.&lt;/p&gt;

&lt;h2&gt;
  
  
  Replicating Re-Rendering
&lt;/h2&gt;

&lt;p&gt;Ok, now let's take the original &lt;code&gt;Counter&lt;/code&gt; component in a different route. This time, let's assume that we have a &lt;code&gt;Counter&lt;/code&gt; that only exists on one tab out of many. We may want to replicate the re-rendering functionality in order to save data when you switch back-and-forth between tabs. That way, as a user, you can work in multiple tabs without losing any data.&lt;/p&gt;

&lt;p&gt;What I've described is basically caching the data outside of the component's state in order to prevent it from resetting. You can approach this with a variety of methods: from Redux, to React Context, to a simple cache object external from the component.&lt;/p&gt;

&lt;p&gt;For our example, we'll do a simple cache just to show the basics. To start, we want to define a cache for us to use and a way for us to update that cache:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;cache&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Counter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setCount&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cache&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;name&lt;/span&gt;&lt;span class="p"&gt;]&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;increment&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setCount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we want a way to update the cache when the component’s &lt;code&gt;name&lt;/code&gt; prop changes (so that we cache data for each user):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;cache&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Counter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setCount&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cache&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;name&lt;/span&gt;&lt;span class="p"&gt;]&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;increment&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setCount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="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;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="nf"&gt;setCount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cache&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;name&lt;/span&gt;&lt;span class="p"&gt;]&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;cache&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;name&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;count&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;props&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This &lt;code&gt;useEffect&lt;/code&gt; will also run during mount and likewise the cleanup function will run during unmount. &lt;/p&gt;

&lt;p&gt;But wait! This code has a problem. When the cleanup function is created, &lt;code&gt;count&lt;/code&gt; is captured within a &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures" rel="noopener noreferrer"&gt;closure&lt;/a&gt; and it’ll save the wrong data into the cache. If we try to fix this by adding &lt;code&gt;count&lt;/code&gt; as a dependency for the hook, then it’ll cause the page to crash due to a circular reference.&lt;/p&gt;

&lt;p&gt;To solve this issue, we can use the &lt;code&gt;useRef&lt;/code&gt; hook in order to use its mutative &lt;code&gt;current&lt;/code&gt; field:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;cache&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Counter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setCount&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cache&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;name&lt;/span&gt;&lt;span class="p"&gt;]&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;countRef&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useRef&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;increment&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;setCount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nx"&gt;countRef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;setCount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cache&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;name&lt;/span&gt;&lt;span class="p"&gt;]&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="nx"&gt;countRef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;cache&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;name&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;

    &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;cache&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;name&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;countRef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;props&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now the cleanup function for the &lt;code&gt;useEffect&lt;/code&gt; will always use the most up-to-date data for &lt;code&gt;count&lt;/code&gt; when setting the cache's value. This is the approach used within &lt;a href="https://codesandbox.io/s/cocky-water-7rz6g" rel="noopener noreferrer"&gt;the codesandbox link&lt;/a&gt; from before for the "Replicating Re-Rendering" section.&lt;/p&gt;

&lt;h1&gt;
  
  
  Wrapping Up
&lt;/h1&gt;

&lt;p&gt;This post was born from the mistakes that my colleagues and I have made in the past. I hope this has helped you understand React a little better and I welcome you to share anything you've learned from prior mistakes!&lt;/p&gt;

&lt;p&gt;Finally, if you've noticed any issues above, please let me know.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.buymeacoffee.com/tiagof" rel="noopener noreferrer"&gt;&lt;br&gt;
&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.buymeacoffee.com%2Fbuttons%2Fv2%2Fdefault-yellow.png" alt="Buy Me A Coffee"&gt;&lt;br&gt;
&lt;/a&gt;&lt;/p&gt;

</description>
      <category>react</category>
      <category>javascript</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
