{"@attributes":{"version":"2.0"},"channel":{"title":"Andrei G\u0103tej","link":"https:\/\/andreigatej.dev\/","description":"Recent content on Andrei G\u0103tej","generator":"Hugo -- gohugo.io","language":"en","lastBuildDate":"Thu, 03 Apr 2025 23:39:59 +0300","item":[{"title":"Debugging Typescript in Neovim","link":"https:\/\/andreigatej.dev\/blog\/debugging-typescript-in-neovim\/","pubDate":"Thu, 03 Apr 2025 23:39:59 +0300","guid":"https:\/\/andreigatej.dev\/blog\/debugging-typescript-in-neovim\/","description":"<blockquote>\n<p>If you prefer a video version of this topic, it can be found <a href=\"https:\/\/www.youtube.com\/watch?v=ieq6DmLKmCU\" target=\"_blank\" rel=\"noopener\">here<\/a>.<\/p>\n<\/blockquote>\n<p>Most of my career as a programmer, I took debugging for granted - all I needed was to press a button or set up some basic configuration and that\u2019s it! At worst, I had to try to understand what I was configuring, but I would confidently say that I have always succeeded in debugging any project I set my mind to (my biggest achievement in this regard was debugging Docker\u2019s engine).<\/p>\n<p>In this article I will share a simple (almost obvious) debugging concept that can be used to debug any program. This time, we will focus on TypeScript and we will see how to debug any TypeScript program both in Neovim. Let\u2019s get started!<\/p>\n<h2 id=\"my-neovim-debugging-set-up\">\n  <span>\n  My Neovim debugging set-up\n  <\/span>\n  <a href=\"#my-neovim-debugging-set-up\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><p><em>You can find my dotfiles <a href=\"https:\/\/github.com\/Andrei0872\/dotfiles\/tree\/master\/nvim\" target=\"_blank\" rel=\"noopener\">here<\/a>.<\/em><\/p>\n<p>As a prerequisite, make sure you have installed <code>js-debug-adapter<\/code>. The easiest way to do so is via Mason.<\/p>\n<p>Then, apart from the well-known <code>mfussenegger\/nvim-dap<\/code> and <code>rcarriga\/nvim-dap-ui<\/code> plugins, there is really nothing special as far as required plugins are concerned. The part where we need to pay a little more attention to is the actual configuration.<\/p>\n<p>First, we need to <a href=\"https:\/\/github.com\/Andrei0872\/dotfiles\/blob\/master\/nvim\/after\/plugin\/dap.lua#L11-L20\" target=\"_blank\" rel=\"noopener\">set up the debug adapter for node<\/a>:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-lua\" data-lang=\"lua\"><span style=\"display:flex;\"><span>dap.adapters <span style=\"color:#f92672\">=<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>      [<span style=\"color:#e6db74\">&#34;pwa-node&#34;<\/span>] <span style=\"color:#f92672\">=<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>        type <span style=\"color:#f92672\">=<\/span> <span style=\"color:#e6db74\">&#34;server&#34;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>        port <span style=\"color:#f92672\">=<\/span> <span style=\"color:#e6db74\">&#34;${port}&#34;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>        executable <span style=\"color:#f92672\">=<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>          command <span style=\"color:#f92672\">=<\/span> <span style=\"color:#e6db74\">&#34;js-debug-adapter&#34;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>          args <span style=\"color:#f92672\">=<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>            <span style=\"color:#e6db74\">&#34;${port}&#34;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>          },\n<\/span><\/span><span style=\"display:flex;\"><span>        },\n<\/span><\/span><span style=\"display:flex;\"><span>      },\n<\/span><\/span><span style=\"display:flex;\"><span>      ...\n<\/span><\/span><span style=\"display:flex;\"><span>          }\n<\/span><\/span><\/code><\/pre><\/div><blockquote>\n<p>A quick clarification: <code>${port}<\/code> means that the port for the debugging session will be resolved automatically.<\/p>\n<\/blockquote>\n<p>Then, we can define some basic debug configuration for TypeScript:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-lua\" data-lang=\"lua\"><span style=\"display:flex;\"><span>dap.configurations[<span style=\"color:#e6db74\">&#34;typescript&#34;<\/span>] <span style=\"color:#f92672\">=<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>        {\n<\/span><\/span><span style=\"display:flex;\"><span>          type <span style=\"color:#f92672\">=<\/span> <span style=\"color:#e6db74\">&#34;pwa-node&#34;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>          request <span style=\"color:#f92672\">=<\/span> <span style=\"color:#e6db74\">&#34;launch&#34;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>          name <span style=\"color:#f92672\">=<\/span> <span style=\"color:#e6db74\">&#34;Launch file&#34;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>          program <span style=\"color:#f92672\">=<\/span> <span style=\"color:#e6db74\">&#34;${file}&#34;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>          cwd <span style=\"color:#f92672\">=<\/span> <span style=\"color:#e6db74\">&#34;${workspaceFolder}&#34;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>        },\n<\/span><\/span><span style=\"display:flex;\"><span>        {\n<\/span><\/span><span style=\"display:flex;\"><span>          type <span style=\"color:#f92672\">=<\/span> <span style=\"color:#e6db74\">&#34;pwa-node&#34;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>          request <span style=\"color:#f92672\">=<\/span> <span style=\"color:#e6db74\">&#34;attach&#34;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>          name <span style=\"color:#f92672\">=<\/span> <span style=\"color:#e6db74\">&#34;Attach to process ID&#34;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>          processId <span style=\"color:#f92672\">=<\/span> utils.pick_process,\n<\/span><\/span><span style=\"display:flex;\"><span>          cwd <span style=\"color:#f92672\">=<\/span> <span style=\"color:#e6db74\">&#34;${workspaceFolder}&#34;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>        },\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p>There are other things we could define and set up (such as keymaps, visual elements, etc.), but, for the scope of this article, what has been presented so far is sufficient. The entire debug configuration can be found <a href=\"https:\/\/github.com\/Andrei0872\/dotfiles\/blob\/master\/nvim\/after\/plugin\/dap.lua\" target=\"_blank\" rel=\"noopener\">here<\/a>. Let\u2019s put what we\u2019ve been configuring so far to practice!<\/p>\n<h2 id=\"debugging-simple-files\">\n  <span>\n  Debugging simple files\n  <\/span>\n  <a href=\"#debugging-simple-files\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><p>Consider this simple TypeScript file:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-tsx\" data-lang=\"tsx\"><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ foo.ts\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span><span style=\"color:#66d9ef\">function<\/span> <span style=\"color:#a6e22e\">foo() {<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#a6e22e\">console<\/span>.<span style=\"color:#a6e22e\">log<\/span>(<span style=\"color:#e6db74\">&#34;hey!&#34;<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">foo<\/span>();\n<\/span><\/span><\/code><\/pre><\/div><p>All we have to do is to:<\/p>\n<ol>\n<li>place a breakpoint using <code>:DapToggleBreakpoint<\/code>, let\u2019s say at <code>foo()<\/code> line<\/li>\n<li>start a debugging session with <code>:DapContinue<\/code><\/li>\n<li>choose <em>Launch file<\/em><\/li>\n<\/ol>\n<p>Then, we should see something like this:<\/p>\n<p><p class=\"markdown-image\">\n  <img src=\".\/images\/image.png\" alt=\"image.png\"  \/>\n<\/p><\/p>\n<p><em>except the lint error.<\/em><\/p>\n<p>So\u2026 it works! However, this is merely the simplest example. In reality, we are dealing with much more complex projects.<\/p>\n<p>In fact, the current configuration does not work with even the simplest <strong>TypeScript project<\/strong>  - i.e. a <code>tsconfig.json<\/code> file and a TypeScript file.<\/p>\n<p>Assuming we have a <code>main.ts<\/code> file:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-tsx\" data-lang=\"tsx\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">function<\/span> <span style=\"color:#a6e22e\">foo<\/span>()<span style=\"color:#f92672\">:<\/span> <span style=\"color:#66d9ef\">string<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#e6db74\">&#34;Andrei&#34;<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">console<\/span>.<span style=\"color:#a6e22e\">log<\/span>(<span style=\"color:#a6e22e\">foo<\/span>());\n<\/span><\/span><\/code><\/pre><\/div><p>and a basic <code>tsconfig.json<\/code>:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-tsx\" data-lang=\"tsx\"><span style=\"display:flex;\"><span>{\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#e6db74\">&#34;compilerOptions&#34;<\/span><span style=\"color:#f92672\">:<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#e6db74\">&#34;sourceMap&#34;<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#66d9ef\">true<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>  },\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#e6db74\">&#34;include&#34;<\/span><span style=\"color:#f92672\">:<\/span> [<span style=\"color:#e6db74\">&#34;.\/main.ts&#34;<\/span>]\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p>then, following the same steps as above, we will notice that <strong>debugging does not work:<\/strong><\/p>\n<div class=\"video-container\">\n    <video controls>\n        <source src=\".\/images\/Screencast_from_24.03.2025_131626.webm\" type=\"\">\n        Your browser does not support the video tag.\n    <\/video>\n<\/div>\n\n<p>At first, it may seem unfortunate - in VS Code this works as a breeze! However, we can see this <em>problem<\/em> from a different perspective - it\u2019s an opportunity to learn something new. In the next section, we will see a simple, yet powerful command that will open so many doors when it comes to debugging.<\/p>\n<h2 id=\"debugging-any-typescript-project\">\n  <span>\n  Debugging any TypeScript project\n  <\/span>\n  <a href=\"#debugging-any-typescript-project\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><p>The way to solve this problem is to leverage other ways of starting the execution of a Node program.<\/p>\n<p>After building our little project with <code>tsc<\/code>, we can successfully run <code>node .\/lib\/main.js<\/code> and <code>'Andrei'<\/code> will be printed to the console.<\/p>\n<blockquote>\n<p>Note: ensure source maps are enabled in <code>tsconfig.json<\/code>.<\/p>\n<\/blockquote>\n<p>The good news is that Node provides the means to start a program in <em>debug<\/em> mode. In <a href=\"https:\/\/nodejs.org\/en\/learn\/getting-started\/debugging#command-line-options\" target=\"_blank\" rel=\"noopener\"><em>Debugging Node.js<\/em><\/a>, we can see that we can use the <code>--inspect-brk<\/code> option:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-bash\" data-lang=\"bash\"><span style=\"display:flex;\"><span>\u279c  ts-playground node --inspect-brk .\/lib\/main.js                                              \n<\/span><\/span><span style=\"display:flex;\"><span>Debugger listening on ws:\/\/127.0.0.1:9229\/16340a2b-7f5c-4bbe-9865-eb361c478b1b\n<\/span><\/span><span style=\"display:flex;\"><span>For help, see: https:\/\/nodejs.org\/en\/docs\/inspector\n<\/span><\/span><\/code><\/pre><\/div><p>As you have noticed, <code>'Andrei'<\/code> has not been printed to the console, which means the program has not actually run. This is expected because <code>--inspect-brk<\/code> will ensure the program will start in <em>debug<\/em> mode and will break at the beginning of its execution.<\/p>\n<p>Then, all we have left to do is to debug the <code>main.ts<\/code> file from Neovim. After placing a breakpoint:<\/p>\n<ol>\n<li>run <code>:DapContinue<\/code><\/li>\n<li>select <em>Attach to process<\/em><\/li>\n<li>find the process that has started due to <code>node --inspect-brk<\/code><\/li>\n<\/ol>\n<p><p class=\"markdown-image\">\n  <img src=\".\/images\/image%201.png\" alt=\"image.png\"  \/>\n<\/p><\/p>\n<ol start=\"4\">\n<li>debugging now works! (if you don\u2019t notice any visual feedback after selecting the process, try any debug command, e.g. <em>step into<\/em>)<\/li>\n<\/ol>\n<p>This entire process, along with other details, can be found in the <a href=\"https:\/\/www.youtube.com\/watch?v=ieq6DmLKmCU\" target=\"_blank\" rel=\"noopener\">video<\/a> I made about debugging TypeScript in Neovim.<\/p>\n<p>If you don\u2019t want the program to stop at the beginning of its execution - for instance, you might want to debug a running server that other programs depend on and any delays to its initialization will result in connection failures - you can simply use <code>--inspect<\/code> instead of <code>--inspect-brk<\/code>.<\/p>\n<blockquote>\n<p>One such instance where <code>--inspect<\/code> makes the difference can be found at <a href=\"https:\/\/www.youtube.com\/watch?v=ReaJnlw9J3Q\" target=\"_blank\" rel=\"noopener\">Debugging TypeScript Language Server in Neovim<\/a> - in the video, we are debugging the TypeScript Language Server that Neovim uses to achieve what\u2019s known as <a href=\"https:\/\/learn.microsoft.com\/en-us\/visualstudio\/ide\/using-intellisense?view=vs-2022\" target=\"_blank\" rel=\"noopener\">IntelliSense<\/a>. And since Neovim LSP\u2019s client needs to establish a connection to the Language Server as soon as possible, breaking the program at its execution will result in not being able to debug the server due to initialization errors (it took me a few hours to realise this - but it was worth it!).<\/p>\n<\/blockquote>\n<p>Lastly, it is worth mentioning that there is an alternative debug client: Chrome\u2019s Dev Tools. After the debug server has started, head over to <em>chrome:\/\/inspect<\/em> and select the appropriate process.<\/p>\n<h2 id=\"conclusion\">\n  <span>\n  Conclusion\n  <\/span>\n  <a href=\"#conclusion\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><p>From a philosophical standpoint, in this article we have learned that an obstacle could be an opportunity to expand our knowledge. Technically speaking, we have seen how to debug basically any program that we can build ourselves - we can simply start it with a debug server attached to it and then attach debug clients to it!<\/p>\n<p>I hope you have found this useful. Thank you for reading!<\/p>\n"},{"title":"Preloading chunks with webpack","link":"https:\/\/andreigatej.dev\/blog\/preloading-chunks-with-webpack\/","pubDate":"Sat, 25 Jan 2025 18:39:38 +0200","guid":"https:\/\/andreigatej.dev\/blog\/preloading-chunks-with-webpack\/","description":"<h2 id=\"introduction\">\n  <span>\n  Introduction\n  <\/span>\n  <a href=\"#introduction\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><p>Webpack is a well-established web bundler that is widely known (among other things) for its rich set of features.<\/p>\n<p>One of the many cool aspects of webpack that I would like to focus on in this article is the concept of <strong>preloading<\/strong>, i.e. what it is, why it is needed and how it works.<\/p>\n<p>Before jumping into the actual topic, we first have to quickly cover some preliminary notions in order to get the most out of this writing.<\/p>\n<h2 id=\"prerequisites\">\n  <span>\n  Prerequisites\n  <\/span>\n  <a href=\"#prerequisites\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><h3 id=\"what-is-a-chunk\">\n  <span>\n  What is a chunk?\n  <\/span>\n  <a href=\"#what-is-a-chunk\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h3><p>When talking about webpack, the concept of a <em>chunk<\/em> can be hardly skipped over.<\/p>\n<p>In simple terms, a chunk is a file that is created as a result of the bundling process.\nThis generated file contains modules (which can be thought of as the initial files and their entire chains of dependencies), as well some <em>runtime code<\/em>, which is code added by webpack in order to achieve <em>its magic<\/em>.<\/p>\n<p>There are multiple kind of chunks:<\/p>\n<ul>\n<li>entry chunks, i.e. chunks created from entry files, declared in the <a href=\"https:\/\/github.com\/Andrei0872\/understanding-webpack\/blob\/master\/examples\/chunk-preload\/webpack.config.js#L9\" target=\"_blank\" rel=\"noopener\"><code>entry<\/code> configuration option<\/a><\/li>\n<li>async chunks, i.e. those created with the <code>import()<\/code> function<\/li>\n<li>chunks created automatically by webpack, e.g. when using <a href=\"https:\/\/andreigatej.dev\/blog\/webpack-splitchunksplugin\/\" target=\"_blank\" rel=\"noopener\">webpacks&rsquo; <code>SplitChunksPlugin<\/code><\/a><\/li>\n<\/ul>\n<!-- raw HTML omitted -->\n<p><em>I have written in more detail about what chunks are in webpack in this <a href=\"https:\/\/andreigatej.dev\/blog\/webpack-what-is-a-chunk\/\" target=\"_blank\" rel=\"noopener\">previous article<\/a>.<\/em><\/p>\n<h3 id=\"the-import-function\">\n  <span>\n  The <code>import()<\/code> function\n  <\/span>\n  <a href=\"#the-import-function\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h3><p>When we talk about preloading chunks, it is somehow implied that we are talking about <strong>async chunks<\/strong>. This kind of chunks are created with the help of\nthe <code>import()<\/code> function, so it is worth spending a few minutes on this.<\/p>\n<p>Whenever webpack detects a call to <code>import('file.js')<\/code>, webpack will automatically create a chunk that corresponds to <code>file.js<\/code>, such that, when that line that invokes the function\nis reached, an actual HTTP request will be made and, through this, the file will be fetched and then integrated into the application.<\/p>\n<p>Why is it needed to talk about this concept before introducing <em>chunk preloading<\/em>?<\/p>\n<p>Preloading, in itself, it is a strategy to optimise the experience of the users on the Internet. It narrows down to giving the browser certain instructions that will fetch\nassets with higher priority (typically, one would use that for resource that are critical to the first navigation to the website).\nWhen we take into account that <code>import()<\/code> essentially creates files (i.e. assets) that will be loaded at a later time, it makes sense to sometimes want to preload such resources with priority.<\/p>\n<p>We will see how to actually instruct webpack to apply this resource hint in a browser context, as well as other underpinnings of preloading in the following sections.<\/p>\n<p><em>As a side note (and as you might have guessed probably), the <code>import()<\/code> function can also be used to achieve <a href=\"https:\/\/www.youtube.com\/watch?v=gttkoU8YTkI&amp;list=PL1Qj0WoSxDryPzQ7ZrR6ymu7M5k3mwEiA&amp;index=11\" target=\"_blank\" rel=\"noopener\">lazy loading<\/a>.<\/em><\/p>\n<h2 id=\"preloading-chunks\">\n  <span>\n  Preloading chunks\n  <\/span>\n  <a href=\"#preloading-chunks\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><p>As hinted at earlier, <em>preloading<\/em> is one of the <a href=\"https:\/\/web.dev\/learn\/performance\/resource-hints#preload\" target=\"_blank\" rel=\"noopener\">resource hints<\/a> available.<\/p>\n<p>Applying this to webpack, this means we can preload <strong>async chunks<\/strong> (e.g. other JavaScript files) as early as possible. What <em>preloading<\/em> means is that the file (i.e. the chunk)\nwill be <strong>fetched<\/strong> over the network, but <strong>not executed<\/strong> yet. Instead of being executed, it will be stored in the browser&rsquo;s cache (we will henceforth assume that the file in question is cacheable) until the line that calls\n<code>import()<\/code> is be reached.<\/p>\n<p>We can tell webpack to preload an async chunk by using the <code>webpackPreload<\/code> magic comment in the <code>import()<\/code> function.\nSo, if we have this line in a file named <code>a.js<\/code>:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-js\" data-lang=\"js\"><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ a.js\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span><span style=\"color:#66d9ef\">import<\/span>(<span style=\"color:#75715e\">\/* webpackPreload: true *\/<\/span> <span style=\"color:#e6db74\">&#39;a1.js&#39;<\/span>)\n<\/span><\/span><\/code><\/pre><\/div><p>We would expect the file <code>a1.js<\/code> to be preloaded. However, as we will see, this will only happen under certain conditions. For instance,\nif <code>a.js<\/code> is part of an <em>entry<\/em> chunk (e.g. for instance, as <code>index.js<\/code> is <a href=\"https:\/\/github.com\/Andrei0872\/understanding-webpack\/blob\/master\/examples\/chunk-preload\/webpack.config.js#L9\" target=\"_blank\" rel=\"noopener\">here<\/a>), then <code>a1.js<\/code> <strong>can&rsquo;t be preloaded<\/strong>. But, if we had something like this<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-js\" data-lang=\"js\"><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ index.js - entry file, mentioned in webpack configuration.\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span><span style=\"color:#66d9ef\">import<\/span>(<span style=\"color:#e6db74\">&#39;a.js&#39;<\/span>)\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ a.js.\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span><span style=\"color:#66d9ef\">import<\/span>(<span style=\"color:#75715e\">\/* webpackPreload: true *\/<\/span> <span style=\"color:#e6db74\">&#39;a1.js&#39;<\/span>)\n<\/span><\/span><\/code><\/pre><\/div><p>Then, when the dynamic import for <code>a.js<\/code> takes place, the chunk that corresponds to <code>a1.js<\/code> <strong>will be preloaded<\/strong>.<\/p>\n<p>We will clarify these facts later on in the article. For now, let&rsquo;s get familiar with the <a href=\"https:\/\/github.com\/Andrei0872\/understanding-webpack\/tree\/master\/examples\/chunk-preload\" target=\"_blank\" rel=\"noopener\">demo application<\/a> which will help us gain a better understanding of this topic:<\/p>\n<pre tabindex=\"0\"><code>\u251c\u2500\u2500 a1.js\n\u251c\u2500\u2500 a2.js\n\u251c\u2500\u2500 a.js\n\u251c\u2500\u2500 b.js\n\u251c\u2500\u2500 index.js\n\u2514\u2500\u2500 webpack.config.js\n<\/code><\/pre><p>The only relevant information with respect to the wepback configuration is that the <code>index.js<\/code> file is the value of the <a href=\"https:\/\/webpack.js.org\/concepts\/entry-points\/\" target=\"_blank\" rel=\"noopener\"><code>entry<\/code> option<\/a>.<\/p>\n<p>The files - or, to use webpack&rsquo;s parlance, <em>modules<\/em> - are not containing any logic more complex that a few simple <strong>dynamic imports<\/strong>. This diagram describes how these modules are connected: <p class=\"markdown-image\">\n  <img src=\".\/images\/module-relations-diagram.png\" alt=\"module relation diagram\"  \/>\n<\/p><\/p>\n<p>A few clarifications regarding the diagram above:<\/p>\n<ul>\n<li>the green bounding rectangles represent <strong>async chunks<\/strong>; these chunks are created because of the use of the <code>import()<\/code> function<\/li>\n<li>the gray bounding rectangle indicates an <strong>entry chunk<\/strong>, i.e. a chunk that will be invariably by the browser<\/li>\n<li>the yellow contained rectangles represent <strong>modules<\/strong> that are part of certain chunks<\/li>\n<li><code>a.js<\/code> dynamically imports <code>a1.js<\/code> with <code>import(\/* webpackChunkName: 'a1', webpackPreload: true *\/ &quot;.\/a1&quot;)<\/code>; which means <code>a1.js<\/code> will be preloaded<\/li>\n<li>all dynamic imports are conditional, e.g. the <code>import()<\/code> function is called, for instance, on a button click; this is relevant because the dynamic chunks are not be loaded immediately<\/li>\n<\/ul>\n<p>Upon page load, only the <code>index<\/code> chunk will be loaded.<\/p>\n<p>What would happen if the line that calls <code>import('b.js')<\/code> is reached?\nSince <code>b<\/code> is an async chunk, what happens is the <code>b.js<\/code> file will be fetched over the network (e.g. through an HTTP request) and then it will be immediately executed.\nThis means there is no preloading involved and, as a result, the user might need to wait for the network request to complete, as well for parsing and executing the file.\n<strong>However<\/strong>, this does not mean the <em>preload<\/em> resource hint should be overused - there could be downsides to it, too, such as cache pollution or redundantly used bandwidth.<br>\nSo, we should always choose our tools wisely!<\/p>\n<p>When importing <code>a.js<\/code>, because it has instructed webpack to <strong>preload<\/strong> <code>a1.js<\/code>, the <code>a1<\/code> chunk <strong>will also be fetched<\/strong> over the network, but not executed. Instead, it will be stored in the browser&rsquo;s cache:<\/p>\n<p><p class=\"markdown-image\">\n  <img src=\".\/images\/a1-req.png\" alt=\"request for a1\"  \/>\n<\/p><\/p>\n<p>The <code>a1.js<\/code> file will be executed only when the line in <code>a.js<\/code> that dynamically imports <code>a1.js<\/code> is reached. Then, <strong>instead of making an HTTP request<\/strong>, the <code>a1.js<\/code> file will be retrieved right away from the cache and executed\nThis it the beauty of preloading assets, in general.<\/p>\n<p>In this small example, we only focused on preloading JavaScript files, but the concept should apply for other resources too, such as fonts, images, videos, etc.<\/p>\n<p><em>I walked through this example also in this <a href=\"https:\/\/www.youtube.com\/watch?v=RHZDvNyWa2Y\" target=\"_blank\" rel=\"noopener\">YouTube video<\/a>.<\/em><\/p>\n<p>In the next section, we will take a look at a slightly more complicated example of preloading, an example I have named, perhaps lacking inspiration, <em>nested preloading<\/em>.<\/p>\n<h2 id=\"nested-preloading\">\n  <span>\n  Nested preloading\n  <\/span>\n  <a href=\"#nested-preloading\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><p>Here is an interesting and practical question worth investigating: <em>What happens if a preloaded chunk also preloads other chunks?<\/em><\/p>\n<p>Getting back to our diagram, there is just a simple addition: <code>a1.js<\/code> dynamically imports <code>a2.js<\/code> with the <code>webpackPreload: true<\/code> magic comment:<\/p>\n<p><p class=\"markdown-image\">\n  <img src=\".\/images\/nested-preloading.png\" alt=\"nested preloading\"  \/>\n<\/p><\/p>\n<p>When will <code>a2.js<\/code>&rsquo;s chunk be fetched? Will it be fetched when the <code>a.js<\/code> file is executed? Or maybe not when <code>a.js<\/code> is executed?<\/p>\n<p>When this question came to mind, I immediately became very intrigued. So intrigued that I had to <a href=\"https:\/\/youtu.be\/n5qT2Z-mrzY?si=JNtCkEnTQGaw-sId\" target=\"_blank\" rel=\"noopener\">make a video<\/a> about it where I explore my hypothesis and final result.<\/p>\n<p>Let&rsquo;s take a step-by-step approach to the questions above.\nFirstly and invariably, <code>index.js<\/code> will be fetched and executed in the browser. This is because <code>index.js<\/code> is an entry file (which makes the <code>index<\/code> chunk an <em>entry chunk<\/em>).\nThen, when <code>a.js<\/code> is imported at a later time, because it preloads <code>a1.js<\/code>, the latter will only be fetched by the browser, but not executed. The file will be executed when the line in <code>a.js<\/code> that imports <code>a1.js<\/code> is reached.<\/p>\n<p>However, what about the fact that <code>a1.js<\/code> (the module that has just been fetched by the browser) <strong>also preloads<\/strong> <code>a2.js<\/code>? Will <code>a2.js<\/code> be fetched now, too?<\/p>\n<p>The answer is <strong>no<\/strong>. The explanation is straightforward: <code>a2.js<\/code> can&rsquo;t be fetched because this only happens when <code>a1.js<\/code> is executed by the browser, i.e. when it is actually required.\nBut, at this point, <code>a1.js<\/code> has <strong>only<\/strong> been fetched and not yet required. So, since <code>a1.js<\/code> is not executed -&gt; <code>a2.js<\/code> can&rsquo;t be fetched.<\/p>\n<p>What we have explored in this section was indeed not very complicated, but, in the next one, we will address a question that requires some under-the-hood knowledge of webpack. Let&rsquo;s see what that is about!<\/p>\n<h2 id=\"not-all-chunks-can-be-preloaded\">\n  <span>\n  Not all chunks can be preloaded\n  <\/span>\n  <a href=\"#not-all-chunks-can-be-preloaded\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><p>Although it may sound counter-intuitive, it is true - <strong>not all async chunks<\/strong> can be preloaded.<\/p>\n<p>Coming back to our demo application, <a href=\"https:\/\/github.com\/Andrei0872\/understanding-webpack\/blob\/master\/examples\/chunk-preload\/index.js#L1-L5\" target=\"_blank\" rel=\"noopener\">let&rsquo;s try preloading <code>a.js<\/code> from <code>index.js<\/code><\/a>:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-js\" data-lang=\"js\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">import<\/span>(<span style=\"color:#75715e\">\/* webpackChunkName: &#39;a&#39;, webpackPreload: true *\/<\/span> <span style=\"color:#e6db74\">&#34;.\/a.js&#34;<\/span>)\n<\/span><\/span><\/code><\/pre><\/div><p>If we reload the browser, we will see no HTTP request for the <code>a.js<\/code> in the network tab, which means the file has not been preloaded.<\/p>\n<p>But, why is that? Why can&rsquo;t <code>a.js<\/code> be preloaded?<\/p>\n<p>Let&rsquo;s bring back the diagram, with a small modification included:<\/p>\n<p><p class=\"markdown-image\">\n  <img src=\".\/images\/preloading-a-chunk.png\" alt=\"preloading the chunk a\"  \/>\n<\/p><\/p>\n<p>One thing that stands out from this diagram is that an <em>entry chunk<\/em> dynamically imports an <em>async chunk<\/em>.\nAnd this is, actually, the reason as to why the <code>a<\/code> chunk can&rsquo;t be preloaded - its <strong>parent chunk<\/strong> is an entry chunk.<\/p>\n<p>Now, another question emerges - why can&rsquo;t an entry chunk preload an async chunk?\nAfter some research, I have found <a href=\"https:\/\/github.com\/jantimon\/html-webpack-plugin\/issues\/1317#issuecomment-704870353\" target=\"_blank\" rel=\"noopener\">this comment<\/a> on an issue:<\/p>\n<blockquote>\n<p>When using preload you must use the script (call import()) within a few seconds [&hellip;] So only use preload when the imported module is mandatory for correct function of the app and the app is useless without it.<\/p>\n<\/blockquote>\n<p>To my understanding, if a chunk is <strong>critical to an entry chunk<\/strong> (this is what is being indicated by using the <em>preload<\/em> resource hint), then the async chunk can be statically imported.\nIt it different if an async chunk needs has other async chunks that are critical for the functionality of the former, because one can&rsquo;t know for sure when the async chunk is actually loaded\/needed.<\/p>\n<p>If you are curious to read the source code that is responsible for all of this magic, you can start from <a href=\"https:\/\/github.com\/webpack\/webpack\/blob\/main\/lib\/prefetch\/ChunkPrefetchPreloadPlugin.js#L46-L48\" target=\"_blank\" rel=\"noopener\">here<\/a>.\nI have also created a <a href=\"https:\/\/github.com\/Andrei0872\/understanding-webpack\" target=\"_blank\" rel=\"noopener\">repo<\/a> where you can find debugging instructions for exploring webpack via the debugger.<\/p>\n<h2 id=\"conclusion\">\n  <span>\n  Conclusion\n  <\/span>\n  <a href=\"#conclusion\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><p>In this article, we have been reminded, first of all, of what <em>preloading<\/em> means - it is a browser resource hint that allows us to fetch resources with priority, as soon as possible.<\/p>\n<p>Then, we have learned about what preloading really means in the context of webpack, the essential role of the <code>import()<\/code> function, what <em>entry chunks<\/em> are, what <em>async chunks<\/em> are and how the ways these are connected influence the preloading behaviour.<\/p>\n<p>Thank you for reading!<\/p>\n"},{"title":"Webpack: what is a chunk?","link":"https:\/\/andreigatej.dev\/blog\/webpack-what-is-a-chunk\/","pubDate":"Wed, 24 Jul 2024 00:00:00 +0000","guid":"https:\/\/andreigatej.dev\/blog\/webpack-what-is-a-chunk\/","description":"<h2 id=\"introduction\">\n  <span>\n  Introduction\n  <\/span>\n  <a href=\"#introduction\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><p>The word <em>chunk<\/em> seems to be ubiquitous in the parlance of web bundlers, especially of <em>webpack<\/em>.<\/p>\n<p>In my opinion, understanding the concept of a <em>chunk<\/em> is essential to understanding how <em>webpack<\/em> works (even at a higher level only). From my experience, everything revolves around chunks - from input files to code splitting and lazy loading, bundle improvements, optimizations and output files.<\/p>\n<p>My goal for this article is to explain as simply and concisely as possible what a chunk is when it comes to <em>webpack<\/em>. The first part will be a bit theoretical, but then we will dive into some practical examples to make sure there are no concepts left unclear. Let\u2019s see how it goes!<\/p>\n<h2 id=\"what-exactly-is-a-chunk\">\n  <span>\n  What exactly is a chunk?\n  <\/span>\n  <a href=\"#what-exactly-is-a-chunk\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><p>Simply speaking, a <em>chunk<\/em> is a <strong>file<\/strong> resulted from the bundle process. But it is not <em>just a file<\/em>, it is a file that<\/p>\n<ol>\n<li>encapsulates modules.<\/li>\n<li>contains generated code, also known as <strong>runtime code<\/strong> - this code plays an important role in making sure the bundled application works as expected when loaded in the browser.<\/li>\n<\/ol>\n<p>I feel that\u2019s all there is to it. What might be left unclear at this point is the difference between a module and a chunk and how they harmoniously work together. Let\u2019s find out in the next section!<\/p>\n<h2 id=\"what-is-the-difference-between-a-chunk-and-a-module\">\n  <span>\n  What is the difference between a chunk and a module?\n  <\/span>\n  <a href=\"#what-is-the-difference-between-a-chunk-and-a-module\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><p>Isn\u2019t a module a file, too? Or, at least, aren\u2019t these two very tied?<\/p>\n<p>In order to clarify things, we first need to make a <strong>distinction<\/strong> between <strong>input files<\/strong> and <strong>output files<\/strong> (i.e. files resulted after bundling).<\/p>\n<p>Initially, a module resides in a file. We could safely state that, in the beginning, there is a 1:1 relationship between a module and a file.<\/p>\n<p><strong>After the bundling process<\/strong>, things will be different - the <em>rule<\/em> we agreed upon above no longer is valid. Every file resulted is a <strong>chunk<\/strong> and the modules that we had initially are just part of those chunks.<\/p>\n<p>So, a module is a file in the beginning, but, after <em>webpack<\/em> has finished bundling, the <strong>resulted files<\/strong> are called <strong>chunks<\/strong> and the <strong>chunks contain modules<\/strong>, as well as runtime code. Webpack uses this runtime code in order to properly tie together all the resulted chunks so that the application becomes functional.<\/p>\n<p>There is good news - this has been the theoretical part of this article. In the next section, we will see some practical examples.<\/p>\n<h2 id=\"how-is-a-chunk-created\">\n  <span>\n  How is a chunk created?\n  <\/span>\n  <a href=\"#how-is-a-chunk-created\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><p>There are multiple ways to create a chunk:<\/p>\n<ol>\n<li>By using the <code>entry<\/code> option. Every file provided to the <code>entry<\/code> option will result in a new chunk.<\/li>\n<li>By using the <code>import()<\/code> function. This function allows us to create chunks and even load them dynamically (e.g. based on runtime conditions).<\/li>\n<li>By using certain webpack plugins, such as <code>SplitChunksPlugin<\/code>.<\/li>\n<\/ol>\n<h3 id=\"creating-chunks-with-the-entry-option\">\n  <span>\n  Creating chunks with the <code>entry<\/code> option\n  <\/span>\n  <a href=\"#creating-chunks-with-the-entry-option\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h3><blockquote>\n<p>The example we will use in this section can be found and tested live <a href=\"https:\/\/stackblitz.com\/edit\/stackblitz-starters-uj3fe7?description=Starter%20project%20for%20Node.js,%20a%20JavaScript%20runtime%20built%20on%20Chrome%27s%20V8%20JavaScript%20engine&amp;file=src%2Fc.js,webpack.config.js,src%2Fa.js,src%2Fa2.js,src%2Fa1.js,dist%2Fc.chunk.js,readme.md&amp;title=node.new%20Starter\" target=\"_blank\" rel=\"noopener\">here<\/a>.<\/p>\n<\/blockquote>\n<p>Suppose the <code>webpack.config.js<\/code> file has the <code>entry<\/code> option configured as follows:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-tsx\" data-lang=\"tsx\"><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">entry<\/span><span style=\"color:#f92672\">:<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">a<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;.\/a.js&#39;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">b<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;.\/b.js&#39;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">c<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;.\/c.js&#39;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  },\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">output<\/span><span style=\"color:#f92672\">:<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">path<\/span>: <span style=\"color:#66d9ef\">path.join<\/span>(<span style=\"color:#a6e22e\">__dirname<\/span>, <span style=\"color:#e6db74\">&#39;dist&#39;<\/span>),\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">filename<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;[name].chunk.js&#39;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  },\n<\/span><\/span><\/code><\/pre><\/div><p>And these are the raw files:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-tsx\" data-lang=\"tsx\"><span style=\"display:flex;\"><span><span style=\"color:#960050;background-color:#1e0010\">\u251c\u2500\u2500<\/span> <span style=\"color:#a6e22e\">a1<\/span>.<span style=\"color:#a6e22e\">js<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#960050;background-color:#1e0010\">\u251c\u2500\u2500<\/span> <span style=\"color:#a6e22e\">a2<\/span>.<span style=\"color:#a6e22e\">js<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#960050;background-color:#1e0010\">\u251c\u2500\u2500<\/span> <span style=\"color:#a6e22e\">a<\/span>.<span style=\"color:#a6e22e\">js<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#960050;background-color:#1e0010\">\u251c\u2500\u2500<\/span> <span style=\"color:#a6e22e\">b<\/span>.<span style=\"color:#a6e22e\">js<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#960050;background-color:#1e0010\">\u2514\u2500\u2500<\/span> <span style=\"color:#a6e22e\">c<\/span>.<span style=\"color:#a6e22e\">js<\/span>\n<\/span><\/span><\/code><\/pre><\/div><p>After running webpack, the <code>dist<\/code> directory will have 3 chunks:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-tsx\" data-lang=\"tsx\"><span style=\"display:flex;\"><span><span style=\"color:#960050;background-color:#1e0010\">\u251c\u2500\u2500<\/span> <span style=\"color:#a6e22e\">a<\/span>.<span style=\"color:#a6e22e\">chunk<\/span>.<span style=\"color:#a6e22e\">js<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#960050;background-color:#1e0010\">\u251c\u2500\u2500<\/span> <span style=\"color:#a6e22e\">b<\/span>.<span style=\"color:#a6e22e\">chunk<\/span>.<span style=\"color:#a6e22e\">js<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#960050;background-color:#1e0010\">\u2514\u2500\u2500<\/span> <span style=\"color:#a6e22e\">c<\/span>.<span style=\"color:#a6e22e\">chunk<\/span>.<span style=\"color:#a6e22e\">js<\/span>\n<\/span><\/span><\/code><\/pre><\/div><p>As stated earlier, each of these chunks will contain modules and some runtime code.<\/p>\n<p>For instance, <code>a.js<\/code> imports both <code>a1.js<\/code> and <code>a2.js<\/code> and, as a result, <code>a.chunk.js<\/code> will contain all these 3 modules (<code>a<\/code>, <code>a1<\/code> and <code>a2<\/code>):<\/p>\n<p><p class=\"markdown-image\">\n  <img src=\".\/images\/Untitled.png\" alt=\"Untitled\"  \/>\n<\/p><\/p>\n<p>We could think of <code>a.js<\/code> as the <em>main<\/em> module of <code>a.chunk.js<\/code> and all of <code>a.js<\/code>&rsquo;s dependencies (as well as their dependencies and so on) will be part of this chunk.\nIf we scroll until the end of the file, we will see the dependencies actually being used:<\/p>\n<p><p class=\"markdown-image\">\n  <img src=\".\/images\/Untitled1.png\" alt=\"Untitled\"  \/>\n<\/p><\/p>\n<p>The same applies for <code>b.chunk.js<\/code> and <code>c.chunk.js<\/code>.<\/p>\n<p>Now, I would like to raise the following questions, knowing that <code>c.js<\/code> also imports <code>a1.js<\/code>.\nWhat do you think <code>c.chunk.js<\/code> will look like? Will there be a <strong>copy<\/strong> of <code>a1.js<\/code> just like in <code>a.chunk.js<\/code> or will webpack find a clever way to not duplicate the module?<\/p>\n<p>Well, as it turns out, <code>a1.js<\/code> will be copied <strong>twice<\/strong> - once in <code>a.chunk.js<\/code> and once in <code>c.chunk.js<\/code>:<\/p>\n<p><p class=\"markdown-image\">\n  <img src=\".\/images\/Untitled2.png\" alt=\"Untitled\"  \/>\n<\/p><\/p>\n<p>This is the default behavior, when no optimizations are applied by webpack. If you want to have more control on such situations, webpack\u2019s <a href=\"https:\/\/andreigatej.dev\/blog\/webpack-splitchunksplugin\/\" target=\"_blank\" rel=\"noopener\">SplitChunksPlugin<\/a> is a powerful way to achieve that.<\/p>\n<h3 id=\"creating-chunks-with-the-import-function\">\n  <span>\n  Creating chunks with the <code>import()<\/code> function\n  <\/span>\n  <a href=\"#creating-chunks-with-the-import-function\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h3><blockquote>\n<p>The example we will use in this section can be found and tested live <a href=\"https:\/\/stackblitz.com\/edit\/stackblitz-starters-e6bzrm?description=Starter%20project%20for%20Node.js,%20a%20JavaScript%20runtime%20built%20on%20Chrome%27s%20V8%20JavaScript%20engine&amp;file=package.json,webpack.config.js,readme.md,src%2Fa.js,src%2Fb.js,src%2Fc.js,src%2Fd.js,dist%2Fa.chunk.js&amp;title=node.new%20Starter\" target=\"_blank\" rel=\"noopener\">here<\/a>.<\/p>\n<\/blockquote>\n<p>This time, we don\u2019t have to dabble with webpack\u2019s configuration too much:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-tsx\" data-lang=\"tsx\"><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ webpack.config.js\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span><span style=\"color:#a6e22e\">entry<\/span><span style=\"color:#f92672\">:<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">a<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;.\/a.js&#39;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  },\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">output<\/span><span style=\"color:#f92672\">:<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">path<\/span>: <span style=\"color:#66d9ef\">path.join<\/span>(<span style=\"color:#a6e22e\">__dirname<\/span>, <span style=\"color:#e6db74\">&#39;dist&#39;<\/span>),\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">clean<\/span>: <span style=\"color:#66d9ef\">true<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">filename<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;[name].chunk.js&#39;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>},\n<\/span><\/span><\/code><\/pre><\/div><p>These are the files we are starting off with:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-tsx\" data-lang=\"tsx\"><span style=\"display:flex;\"><span><span style=\"color:#960050;background-color:#1e0010\">\u251c\u2500\u2500<\/span> <span style=\"color:#a6e22e\">a<\/span>.<span style=\"color:#a6e22e\">js<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#960050;background-color:#1e0010\">\u251c\u2500\u2500<\/span> <span style=\"color:#a6e22e\">b<\/span>.<span style=\"color:#a6e22e\">js<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#960050;background-color:#1e0010\">\u251c\u2500\u2500<\/span> <span style=\"color:#a6e22e\">c<\/span>.<span style=\"color:#a6e22e\">js<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#960050;background-color:#1e0010\">\u2514\u2500\u2500<\/span> <span style=\"color:#a6e22e\">d<\/span>.<span style=\"color:#a6e22e\">js<\/span>\n<\/span><\/span><\/code><\/pre><\/div><p>The interesting bits reside in the <code>a.js<\/code> file, while all the other files simply export a string:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-tsx\" data-lang=\"tsx\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">import<\/span> <span style=\"color:#a6e22e\">d<\/span> <span style=\"color:#66d9ef\">from<\/span> <span style=\"color:#e6db74\">&#39;.\/d&#39;<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">console<\/span>.<span style=\"color:#a6e22e\">log<\/span>(<span style=\"color:#a6e22e\">d<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">import<\/span>(<span style=\"color:#e6db74\">&#39;.\/b.js&#39;<\/span>).<span style=\"color:#a6e22e\">then<\/span>(() <span style=\"color:#f92672\">=&gt;<\/span> <span style=\"color:#a6e22e\">console<\/span>.<span style=\"color:#a6e22e\">log<\/span>(<span style=\"color:#e6db74\">&#39;[b] ready!&#39;<\/span>));\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">someCondition<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">true<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#a6e22e\">someCondition<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">import<\/span>(<span style=\"color:#e6db74\">&#39;.\/c.js&#39;<\/span>).<span style=\"color:#a6e22e\">then<\/span>(() <span style=\"color:#f92672\">=&gt;<\/span> <span style=\"color:#a6e22e\">console<\/span>.<span style=\"color:#a6e22e\">log<\/span>(<span style=\"color:#e6db74\">&#39;[c] ready!&#39;<\/span>));\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">export<\/span> <span style=\"color:#66d9ef\">default<\/span> <span style=\"color:#e6db74\">&#39;a&#39;<\/span>;\n<\/span><\/span><\/code><\/pre><\/div><p>The <code>import()<\/code> function has been used twice, so we expect at least two resulting chunks after the bundling process.<\/p>\n<p>Let\u2019s run webpack with <code>npm run dev<\/code> and see what the output is:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-tsx\" data-lang=\"tsx\"><span style=\"display:flex;\"><span><span style=\"color:#960050;background-color:#1e0010\">\u251c\u2500\u2500<\/span> <span style=\"color:#ae81ff\">1<\/span>.<span style=\"color:#a6e22e\">chunk<\/span>.<span style=\"color:#a6e22e\">js<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#960050;background-color:#1e0010\">\u251c\u2500\u2500<\/span> <span style=\"color:#ae81ff\">2<\/span>.<span style=\"color:#a6e22e\">chunk<\/span>.<span style=\"color:#a6e22e\">js<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#960050;background-color:#1e0010\">\u2514\u2500\u2500<\/span> <span style=\"color:#a6e22e\">a<\/span>.<span style=\"color:#a6e22e\">chunk<\/span>.<span style=\"color:#a6e22e\">js<\/span>\n<\/span><\/span><\/code><\/pre><\/div><p>Actually, there are 3 chunks. <code>a.chunk.js<\/code> is the <strong>entry chunk<\/strong> (i.e. the one that corresponds to the <code>entry<\/code> field), while <code>1.chunk.js<\/code> and <code>2.chunk.js<\/code> map to <code>b.js<\/code>&rsquo;s chunk and <code>c.js<\/code>&rsquo;s chunk, respectively. The <code>d.js<\/code> module simply belongs to <code>a.chunk.js<\/code>.<\/p>\n<p>If we take a look at what the <code>import()<\/code> functions have been translated into, we shall see the following <em>runtime code<\/em>:<\/p>\n<p><p class=\"markdown-image\">\n  <img src=\".\/images\/Untitled3.png\" alt=\"Untitled\"  \/>\n<\/p><\/p>\n<p><code>import('.\/b.js')<\/code> has turned into <code>__webpack_require__.e(\/* import() *\/ 1)<\/code>. The <code>e<\/code> function, along with other cleverly defined functions, are part of the so-called <em>runtime code.<\/em> Such code, in the context of the <code>import()<\/code> function, is responsible for loading chunks over the network (e.g. via a <code>script<\/code> tag and JSONP), as well as for integrating the constituent modules of loaded chunks so that the entire bundled application is functional.<\/p>\n<p>With the help of the <code>import()<\/code> function, developers can achieve, besides code splitting, <strong>lazy loading<\/strong>. It also has an interesting trait - it can be used with <strong>dynamic arguments<\/strong>. I have written an article on this topic <a href=\"https:\/\/andreigatej.dev\/blog\/webpack-import-function-dynamic-arguments\/\" target=\"_blank\" rel=\"noopener\">here<\/a>.<\/p>\n<h3 id=\"creating-chunks-via-webpack-plugins\">\n  <span>\n  Creating chunks via webpack plugins\n  <\/span>\n  <a href=\"#creating-chunks-via-webpack-plugins\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h3><p>This topic deserves an article on its own, which is why I have written <a href=\"https:\/\/andreigatej.dev\/blog\/webpack-splitchunksplugin\/\" target=\"_blank\" rel=\"noopener\">Webpack: An in-depth introduction to SplitChunksPlugin<\/a>. In that article, I share my findings about how <code>SplitChunksPlugin<\/code> acts as an optimization layer in the bundling process.<\/p>\n<p>One case where <code>SplitChunksPlugin<\/code> could create new chunks is when there are <em>heavy<\/em> modules (i.e. files with a lot of lines of code) that are frequently imported in the application. This plugin will <em>magically<\/em> group such heavy modules in chunks so that they are loaded only once and not duplicated at all. This could be a huge performance improvement, especially on devices with low CPU power or low network bandwidth.<\/p>\n<h2 id=\"conclusion\">\n  <span>\n  Conclusion\n  <\/span>\n  <a href=\"#conclusion\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><p>I hope this fairly short article shed a light on what a chunk is in the context of webpack. For me, understanding this concept was a turning point in my webpack learning journey. After that, I could properly focus on specific features and other advanced concepts.<\/p>\n<p>Thank you for reading!<\/p>\n"},{"title":"The underlying mechanisms of React\u2019s concurrent mode","link":"https:\/\/andreigatej.dev\/blog\/the-underlying-mechanisms-of-reacts-concurrent-mode\/","pubDate":"Sat, 19 Aug 2023 16:43:11 +0300","guid":"https:\/\/andreigatej.dev\/blog\/the-underlying-mechanisms-of-reacts-concurrent-mode\/","description":"<!-- raw HTML omitted -->\n<h2 id=\"introduction\">\n  <span>\n  Introduction\n  <\/span>\n  <a href=\"#introduction\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><p>It\u2019s not the first time React seemed like magic to me. But, this time, reading the <em><a href=\"https:\/\/react.dev\/reference\/react\/useTransition#marking-a-state-update-as-a-non-blocking-transition\" target=\"_blank\" rel=\"noopener\">Marking a state update as a non-blocking transition<\/a><\/em> section from the <code>useTransition<\/code> documentation really caught my attention.<\/p>\n<p>In this article, besides sharing how the concurrent mode works with the help of React\u2019s transitions, I will also walk you through my reasoning process that I employ whenever I try to arrive from <em>having no idea how this works<\/em> to <em><strong><strong><strong><strong><strong><strong><strong><strong>I finally get it!<\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/em>.<\/p>\n<p>It\u2019s worth mentioning that, this time, I took a <strong><strong><strong><strong>roundabout approach<\/strong><\/strong><\/strong><\/strong> to explaining a concept. We will heavily make use of the <code>startTransition<\/code> function from the <code>useTransition<\/code> hook to finally arrive to how <em><strong><strong><strong><strong><strong><strong><strong>concurrent mode<\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/em> works. First, we will introduce the problem, then we will test some assertions and, at the end, things should(and hopefully) make sense.<\/p>\n<p>Let\u2019s get started!<\/p>\n<h2 id=\"introducing-the-problem\">\n  <span>\n  Introducing the problem\n  <\/span>\n  <a href=\"#introducing-the-problem\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><p><a href=\"https:\/\/codesandbox.io\/s\/objective-ride-qkznlp?file=\/App.js\" target=\"_blank\" rel=\"noopener\">Here is the link<\/a> to the CodeSandbox application that this article will be based on. As mentioned earlier, this example has been extracted from <a href=\"https:\/\/react.dev\/reference\/react\/useTransition#marking-a-state-update-as-a-non-blocking-transition\" target=\"_blank\" rel=\"noopener\">this section<\/a> of the React\u2019s <code>useTransition<\/code> documentation:<\/p>\n<p><p class=\"markdown-image\">\n  <img src=\"images\/Untitled.png\" alt=\"Untitled\"  \/>\n<\/p><\/p>\n<p>The <code>PostTab<\/code> is slow in terms of rendering time:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-jsx\" data-lang=\"jsx\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">PostsTab<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">memo<\/span>(<span style=\"color:#66d9ef\">function<\/span> <span style=\"color:#a6e22e\">PostsTab<\/span>() {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#75715e\">\/\/ Log once. The actual slowdown is inside SlowPost.\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>  <span style=\"color:#a6e22e\">console<\/span>.<span style=\"color:#a6e22e\">log<\/span>(<span style=\"color:#e6db74\">&#34;[ARTIFICIALLY SLOW] Rendering 500 &lt;SlowPost \/&gt;&#34;<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">let<\/span> <span style=\"color:#a6e22e\">items<\/span> <span style=\"color:#f92672\">=<\/span> [];\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">for<\/span> (<span style=\"color:#66d9ef\">let<\/span> <span style=\"color:#a6e22e\">i<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#ae81ff\">0<\/span>; <span style=\"color:#a6e22e\">i<\/span> <span style=\"color:#f92672\">&lt;<\/span> <span style=\"color:#ae81ff\">1000<\/span>; <span style=\"color:#a6e22e\">i<\/span><span style=\"color:#f92672\">++<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">items<\/span>.<span style=\"color:#a6e22e\">push<\/span>(&lt;<span style=\"color:#f92672\">SlowPost<\/span> <span style=\"color:#a6e22e\">key<\/span><span style=\"color:#f92672\">=<\/span>{<span style=\"color:#a6e22e\">i<\/span>} <span style=\"color:#a6e22e\">index<\/span><span style=\"color:#f92672\">=<\/span>{<span style=\"color:#a6e22e\">i<\/span>} \/&gt;);\n<\/span><\/span><span style=\"display:flex;\"><span>  }\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">return<\/span> &lt;<span style=\"color:#f92672\">ul<\/span> <span style=\"color:#a6e22e\">className<\/span><span style=\"color:#f92672\">=<\/span><span style=\"color:#e6db74\">&#34;items&#34;<\/span>&gt;{<span style=\"color:#a6e22e\">items<\/span>}&lt;\/<span style=\"color:#f92672\">ul<\/span>&gt;;\n<\/span><\/span><span style=\"display:flex;\"><span>});\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">function<\/span> <span style=\"color:#a6e22e\">SlowPost<\/span>({ <span style=\"color:#a6e22e\">index<\/span> }) {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">console<\/span>.<span style=\"color:#a6e22e\">log<\/span>(<span style=\"color:#e6db74\">&#34;rendering post &#34;<\/span> <span style=\"color:#f92672\">+<\/span> <span style=\"color:#a6e22e\">index<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">let<\/span> <span style=\"color:#a6e22e\">startTime<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">performance<\/span>.<span style=\"color:#a6e22e\">now<\/span>();\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">while<\/span> (<span style=\"color:#a6e22e\">performance<\/span>.<span style=\"color:#a6e22e\">now<\/span>() <span style=\"color:#f92672\">-<\/span> <span style=\"color:#a6e22e\">startTime<\/span> <span style=\"color:#f92672\">&lt;<\/span> <span style=\"color:#ae81ff\">1<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#75715e\">\/\/ Do nothing for 1 ms per item to emulate extremely slow code\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>  }\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">return<\/span> &lt;<span style=\"color:#f92672\">li<\/span> <span style=\"color:#a6e22e\">className<\/span><span style=\"color:#f92672\">=<\/span><span style=\"color:#e6db74\">&#34;item&#34;<\/span>&gt;<span style=\"color:#a6e22e\">Post<\/span> <span style=\"color:#960050;background-color:#1e0010\">#<\/span>{<span style=\"color:#a6e22e\">index<\/span> <span style=\"color:#f92672\">+<\/span> <span style=\"color:#ae81ff\">1<\/span>}&lt;\/<span style=\"color:#f92672\">li<\/span>&gt;;\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p>The <code>PostsTab<\/code> component acts as a container for multiple <code>SlowPost<\/code> components, each of them requiring 1 millisecond to render. So, if there are 1000 posts to be rendered and each post corresponds to a <code>SlowPost<\/code> component, the total rendering time for the <code>PostsTab<\/code> component will be 1 second. One would expect that, during this period of <strong>1 second<\/strong>, the <strong>browser would become unresponsive<\/strong> to user interaction. However, this is <strong>not going to happen<\/strong> due to <strong>setting the state<\/strong> that would <em><strong><strong><strong><strong>normally<\/strong><\/strong><\/strong><\/strong><\/em> result in a noticeable freeze in a <code>startTransition<\/code> callback:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-jsx\" data-lang=\"jsx\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">function<\/span> <span style=\"color:#a6e22e\">selectTab<\/span>(<span style=\"color:#a6e22e\">nextTab<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">startTransition<\/span>(() =&gt; {\n<\/span><\/span><span style=\"display:flex;\"><span>\t\t\t<span style=\"color:#a6e22e\">setTab<\/span>(<span style=\"color:#a6e22e\">nextTab<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>    });\n<\/span><\/span><span style=\"display:flex;\"><span>  }\n<\/span><\/span><\/code><\/pre><\/div><p>In order to <strong>see this in action<\/strong>:<\/p>\n<ol>\n<li>while being on the <em><strong><strong>About<\/strong><\/strong><\/em> page, select the <em><strong><strong><strong>Posts (slow)<\/strong><\/strong><\/strong><\/em> tab<\/li>\n<li>immediately(i.e. while the <em>Posts<\/em> page isn\u2019t shown in the page) click on the <em><strong><strong><strong>Contact<\/strong><\/strong><\/strong><\/em> page<\/li>\n<\/ol>\n<p>If the <em>Posts<\/em> page seems to show too quickly, you can increase the number of posts from 1000(i.e. 1 second to render) to a larger amount.<\/p>\n<p>As you can notice, there was no delay after quickly selecting the <strong><strong><strong><strong>Contact<\/strong><\/strong><\/strong><\/strong> page right after selecting the <strong><strong><strong>Posts<\/strong><\/strong><\/strong> page. Using <code>startTransition<\/code> is what makes this smooth user experience possible.<\/p>\n<p>In order to <strong><strong><strong><strong><strong><strong><strong>feel the magic<\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong> of <code>startTransition<\/code>, try commenting out the <code>startTransition<\/code> parts and follow the steps from above:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-jsx\" data-lang=\"jsx\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">function<\/span> <span style=\"color:#a6e22e\">selectTab<\/span>(<span style=\"color:#a6e22e\">nextTab<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/    startTransition(() =&gt; {\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>\t\t\t<span style=\"color:#75715e\">\/\/ If `nextTab === &#39;post&#39;` -&gt; noticeable browser freeze for the user!\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>      <span style=\"color:#a6e22e\">setTab<\/span>(<span style=\"color:#a6e22e\">nextTab<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/    });\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>  }\n<\/span><\/span><\/code><\/pre><\/div><p>Now, if, for example, 2000 posts must be rendered, you should notice a 2 second freeze period after clicking on the <strong><strong><strong><strong>Posts (slow)<\/strong><\/strong><\/strong><\/strong> tab.<\/p>\n<p>After seeing the difference the <code>startTransition<\/code> function makes, I felt deeply impressed. It really seemed like something magical must be going on. I\u2019d lie if I were to say that it didn\u2019t keep me up at night.<\/p>\n<p>In the following sections, we are going to go through my reasoning process and, hopefully, at the end of it, we will understand what makes this user experience possible.<\/p>\n<h2 id=\"why-does-the-browser-freeze-when-not-using-starttransition\">\n  <span>\n  Why does the browser freeze when not using startTransition?\n  <\/span>\n  <a href=\"#why-does-the-browser-freeze-when-not-using-starttransition\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><p><em>For reference, <a href=\"https:\/\/codesandbox.io\/s\/objective-ride-qkznlp?file=\/PostsTab.js\" target=\"_blank\" rel=\"noopener\">here is the CodeSandbox<\/a> for the example in question.<\/em><\/p>\n<p>This was the question that, in my opinion, set me on the right track. By finding out the answer to this question, we will essentially find out the problem that the <code>startTransition<\/code> function is trying to solve, and I think this is a great starting point.<\/p>\n<p>The key to finding this answer is understanding what really <em>rendering<\/em> means in the context of React. <em><strong><strong><strong><strong><strong><strong><strong>What does it mean for a component to be rendered?<\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/em> - in very simple terms(I don\u2019t even think there could be more to be said here, to be honest), <em>rendering<\/em> means to invoke a function that represents a React component.<\/p>\n<p>Let\u2019s bring up once again the part that indicates a slow render:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-jsx\" data-lang=\"jsx\"><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ ==========================================================\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span><span style=\"color:#66d9ef\">function<\/span> <span style=\"color:#a6e22e\">SlowPost<\/span>({ <span style=\"color:#a6e22e\">index<\/span> }) {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">console<\/span>.<span style=\"color:#a6e22e\">log<\/span>(<span style=\"color:#e6db74\">&#34;rendering post &#34;<\/span> <span style=\"color:#f92672\">+<\/span> <span style=\"color:#a6e22e\">index<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">let<\/span> <span style=\"color:#a6e22e\">startTime<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">performance<\/span>.<span style=\"color:#a6e22e\">now<\/span>();\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">while<\/span> (<span style=\"color:#a6e22e\">performance<\/span>.<span style=\"color:#a6e22e\">now<\/span>() <span style=\"color:#f92672\">-<\/span> <span style=\"color:#a6e22e\">startTime<\/span> <span style=\"color:#f92672\">&lt;<\/span> <span style=\"color:#ae81ff\">1<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#75715e\">\/\/ Do nothing for 1 ms per item to emulate extremely slow code\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>  }\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">return<\/span> &lt;<span style=\"color:#f92672\">li<\/span> <span style=\"color:#a6e22e\">className<\/span><span style=\"color:#f92672\">=<\/span><span style=\"color:#e6db74\">&#34;item&#34;<\/span>&gt;<span style=\"color:#a6e22e\">Post<\/span> <span style=\"color:#960050;background-color:#1e0010\">#<\/span>{<span style=\"color:#a6e22e\">index<\/span> <span style=\"color:#f92672\">+<\/span> <span style=\"color:#ae81ff\">1<\/span>}&lt;\/<span style=\"color:#f92672\">li<\/span>&gt;;\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ ==========================================================\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ Some details have been skipped for brevity.\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span><span style=\"color:#66d9ef\">function<\/span> <span style=\"color:#a6e22e\">PostsTab<\/span>() {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">items<\/span> <span style=\"color:#f92672\">=<\/span> [];\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">for<\/span> (<span style=\"color:#66d9ef\">let<\/span> <span style=\"color:#a6e22e\">i<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#ae81ff\">0<\/span>; <span style=\"color:#a6e22e\">i<\/span> <span style=\"color:#f92672\">&lt;<\/span> <span style=\"color:#ae81ff\">1000<\/span>; <span style=\"color:#a6e22e\">i<\/span><span style=\"color:#f92672\">++<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>\t\t<span style=\"color:#a6e22e\">items<\/span>.<span style=\"color:#a6e22e\">push<\/span>(&lt;<span style=\"color:#f92672\">SlowPost<\/span> <span style=\"color:#a6e22e\">index<\/span><span style=\"color:#f92672\">=<\/span>{<span style=\"color:#a6e22e\">i<\/span>} \/&gt;)\n<\/span><\/span><span style=\"display:flex;\"><span>\t}\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p>So, rendering the <code>PostsTab<\/code> component means executing the <code>PostsTab()<\/code> function. This implies that the <code>SlowPost<\/code> function will have to be invoked 1000 times and, since invoking <code>SlowPost<\/code> requires 1 millisecond, the total rendering time will be 1 second.<\/p>\n<p>Now that we have got an understanding of that <strong><strong><strong><strong><strong>rendering<\/strong><\/strong><\/strong><\/strong><\/strong> means, we have also got the first hint: it\u2019s the <em>rendering<\/em> that takes a lot of time, <strong>not the browser building the web page<\/strong>. Or, in other words, it\u2019s the <em><strong><strong><strong><strong><strong><strong><strong>rendering phase,<\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/em> not the action of <strong><strong><strong><strong><strong>committing<\/strong><\/strong><\/strong><\/strong><\/strong> rendered elements to the real DOM.<\/p>\n<blockquote>\n<p>Yes, there is a clear distinction between <em>rendering<\/em>(i.e. invoking functions while determining new changes that would have to be eventually be shown in the real DOM) and <strong><strong>committing<\/strong><\/strong> to the DOM. What\u2019s also interesting is that the <strong><strong><strong>commit<\/strong><\/strong><\/strong> phase does not have to always come after the <strong><strong><strong>render<\/strong><\/strong><\/strong> phase. For instance, a tree of Virtual DOM nodes can be rendered, but their <strong><strong><strong><strong><strong>commitment<\/strong><\/strong><\/strong><\/strong><\/strong> to the real DOM can be delayed. Such example can be found in an article I wrote a while ago, <em><a href=\"https:\/\/andreigatej.dev\/blog\/on-react-suspense-throttling\/#nested-suspense-components\" target=\"_blank\" rel=\"noopener\">On React Suspense\u2019s throttling<\/a>.<\/em><\/p>\n<\/blockquote>\n<p>Concretely, what\u2019s really going on when using this logic:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-jsx\" data-lang=\"jsx\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">function<\/span> <span style=\"color:#a6e22e\">selectTab<\/span>(<span style=\"color:#a6e22e\">nextTab<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/    startTransition(() =&gt; {\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>      <span style=\"color:#a6e22e\">setTab<\/span>(<span style=\"color:#a6e22e\">nextTab<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/    });\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>  }\n<\/span><\/span><\/code><\/pre><\/div><p>is that, after clicking on <em><strong><strong><strong>Posts (slow)<\/strong><\/strong><\/strong><\/em> React will render the <strong>entire tree synchronously<\/strong>. It\u2019s similar to doing something like this:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-jsx\" data-lang=\"jsx\"><span style=\"display:flex;\"><span> <span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">renderSlowPost<\/span> <span style=\"color:#f92672\">=<\/span> (...<span style=\"color:#a6e22e\">args<\/span>) =&gt; {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">startTime<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">performance<\/span>.<span style=\"color:#a6e22e\">now<\/span>();\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">while<\/span> (<span style=\"color:#a6e22e\">performance<\/span>.<span style=\"color:#a6e22e\">now<\/span>() <span style=\"color:#f92672\">-<\/span> <span style=\"color:#a6e22e\">startTime<\/span> <span style=\"color:#f92672\">&lt;<\/span> <span style=\"color:#ae81ff\">1<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#75715e\">\/\/ Do nothing for 1 ms per item to emulate extremely slow code\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>  }\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">return<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">renderPostsTab<\/span> <span style=\"color:#f92672\">=<\/span> (...<span style=\"color:#a6e22e\">args<\/span>) =&gt; {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">for<\/span> (<span style=\"color:#66d9ef\">let<\/span> <span style=\"color:#a6e22e\">postIdx<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#ae81ff\">0<\/span>; <span style=\"color:#a6e22e\">postIdx<\/span> <span style=\"color:#f92672\">&lt;<\/span> <span style=\"color:#ae81ff\">1000<\/span>; <span style=\"color:#a6e22e\">postIdx<\/span><span style=\"color:#f92672\">++<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">renderSlowPost<\/span>();\n<\/span><\/span><span style=\"display:flex;\"><span>  }\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ ============================================================\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">selectSlowPostsTab<\/span> <span style=\"color:#f92672\">=<\/span> () =&gt; {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#75715e\">\/\/ This takes 1 second - a lot!\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>  <span style=\"color:#a6e22e\">renderPostsTab<\/span>();\n<\/span><\/span><span style=\"display:flex;\"><span>  \n<\/span><\/span><span style=\"display:flex;\"><span> <span style=\"color:#75715e\">\/\/ This will be executed after 1 second(i.e. after the above function returns).\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>  <span style=\"color:#a6e22e\">commitChangesToTheRealDOM<\/span>();\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p>Of course, in reality, it\u2019s a lot more complicated than that. But the above pseudo-code should highlight where the problem lies - <em>rendering<\/em>(i.e. invoking some JavaScript functions) takes a lot of time, so the user will notice the delay.<\/p>\n<p>By now, we have understood where the problem lies and that, somehow, the <code>startTransition<\/code> function <em>magically<\/em> solves this by wrapping the functions that sets the state:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-jsx\" data-lang=\"jsx\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">function<\/span> <span style=\"color:#a6e22e\">selectTab<\/span>(<span style=\"color:#a6e22e\">nextTab<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">startTransition<\/span>(() =&gt; {\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#a6e22e\">setTab<\/span>(<span style=\"color:#a6e22e\">nextTab<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>    });\n<\/span><\/span><span style=\"display:flex;\"><span>  }\n<\/span><\/span><\/code><\/pre><\/div><p>There are also a few things that are worth taking into account: the fact that JavaScript\u2019s execution model is <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/JavaScript\/Event_loop#run-to-completion\" target=\"_blank\" rel=\"noopener\">run-to-completion<\/a>, which means that a function can\u2019t be interrupted from its execution and resumed later. For example, in languages like C, this is possible. What this language feature means to us is that the execution of <code>renderPostsTab<\/code><\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-jsx\" data-lang=\"jsx\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">renderSlowPost<\/span> <span style=\"color:#f92672\">=<\/span> (...<span style=\"color:#a6e22e\">args<\/span>) =&gt; {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">startTime<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">performance<\/span>.<span style=\"color:#a6e22e\">now<\/span>();\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">while<\/span> (<span style=\"color:#a6e22e\">performance<\/span>.<span style=\"color:#a6e22e\">now<\/span>() <span style=\"color:#f92672\">-<\/span> <span style=\"color:#a6e22e\">startTime<\/span> <span style=\"color:#f92672\">&lt;<\/span> <span style=\"color:#ae81ff\">1<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#75715e\">\/\/ Do nothing for 1 ms per item to emulate extremely slow code\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>  }\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">return<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">renderPostsTab<\/span> <span style=\"color:#f92672\">=<\/span> (...<span style=\"color:#a6e22e\">args<\/span>) =&gt; {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">for<\/span> (<span style=\"color:#66d9ef\">let<\/span> <span style=\"color:#a6e22e\">postIdx<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#ae81ff\">0<\/span>; <span style=\"color:#a6e22e\">postIdx<\/span> <span style=\"color:#f92672\">&lt;<\/span> <span style=\"color:#ae81ff\">1000<\/span>; <span style=\"color:#a6e22e\">postIdx<\/span><span style=\"color:#f92672\">++<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">renderSlowPost<\/span>();\n<\/span><\/span><span style=\"display:flex;\"><span>  }\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p>can\u2019t be stopped so that other tasks with high priority get the chance to be executed, <strong><strong><strong><strong><strong><strong>unless<\/strong><\/strong><\/strong><\/strong><\/strong><\/strong> we <strong>apply some good practices<\/strong>.<\/p>\n<p>Intuitively, if a task\/function takes too long to be processed at once, we can break it into smaller chunks and process them periodically by interleaving them with other tasks that also need time on the main thread.<\/p>\n<p>In the section, we are going to state a hypothesis as to how <code>startTransition<\/code> really works and then we are going to prove it. This will, in the end, lead us to a better understanding of React\u2019s <strong><strong><strong><strong><strong><strong><strong><strong>concurrent mode.<\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/p>\n<h2 id=\"how-starttransition-works---a-hypothesis\">\n  <span>\n  How startTransition works - a hypothesis\n  <\/span>\n  <a href=\"#how-starttransition-works---a-hypothesis\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><p>We have agreed upon that dividing an expanse task into smaller ones is a good approach to solving the problem we are facing - the browser becoming unresponsive to user interactions because rendering requires too much time.<\/p>\n<p>This is the <strong>hypothesis<\/strong> as to what the <code>startTransition<\/code> function causes - <strong>rendering expensive tasks in chunks<\/strong> and <strong>yielding to the browser\u2019s main thread<\/strong> periodically, so that the page stays responsive. In other words, <code>startTransition<\/code> will kick off the <strong><strong><strong><strong><strong><strong><strong><strong>concurrent mode.<\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong> Notice, though, that <code>startTransition<\/code> is <strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong>not <p class=\"markdown-image\">\n  <img src=\"images\/Untitled%201.png\" alt=\"Untitled\"  \/>\n<\/p>responsible for breaking a task into smaller tasks<\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong> - that\u2019s up to the developer. We will see an example of this later in this article.<\/p>\n<p>First, let\u2019s test whether what\u2019s been stated above it indeed true. For that, let\u2019s bring once again <a href=\"https:\/\/codesandbox.io\/s\/objective-ride-qkznlp?file=\/PostsTab.js\" target=\"_blank\" rel=\"noopener\">the CodeSandbox application<\/a>:<\/p>\n<p><p class=\"markdown-image\">\n  <img src=\"images\/Untitled%201.png\" alt=\"Untitled\"  \/>\n<\/p><\/p>\n<p><em>Notice some relevant <code>console.log()<\/code> calls. The most important would be the one in the <code>SlowPost<\/code> component.<\/em><\/p>\n<p>We have already tested before that <code>startTransition<\/code> works: clicking on <strong><strong><strong><strong>Posts (slow)<\/strong><\/strong><\/strong><\/strong> and then, immediately after that, on the <em><strong><strong><strong>Contact<\/strong><\/strong><\/strong><\/em> tab, will not cause the browser to freeze at all. Now, we need to test our hypothesis and, for that, we need to go deeper into how React really works.<\/p>\n<p><strong>But first<\/strong>, let\u2019s clarify a crucial aspect - <em><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong>what does it mean to yield to the browser\u2019s main thread?<\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/em><\/p>\n<h3 id=\"yielding-to-the-main-thread\">\n  <span>\n  Yielding to the main thread\n  <\/span>\n  <a href=\"#yielding-to-the-main-thread\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h3><p>JavaScript runs in a single-threaded environment. Yes, one can make use of other additional threads(e.g. via <code>WebWorker<\/code>, <code>ServiceWorker<\/code>), but there is <strong>only one main thread<\/strong>, also known as the <em>UI<\/em> thread. This thread is responsible not only for tasks such as executing the JavaScript code written by developers(e.g. event listeners), but also responsible for rendering tasks, parsing CSS, etc. Whenever a function is executed, the entire main thread is <em><strong><strong><strong>blocked<\/strong><\/strong><\/strong><\/em> while executing that function, because the <strong>main thread can run only one task at a time<\/strong>. This is the reason a web page could become unresponsive - the main thread is busy executing some logic.<\/p>\n<blockquote>\n<p>There is very interesting article which presents the <a href=\"https:\/\/web.dev\/rail\/\" target=\"_blank\" rel=\"noopener\">RAIL model<\/a> - in there, you can see which delays are acceptable depending on which situations, how much milliseconds should tasks take and much more.<\/p>\n<\/blockquote>\n<p><strong><strong><strong><strong><strong><strong><strong><strong><strong>Yielding to the main thread<\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong> means <em><strong><strong><strong><strong><strong><strong>interrupting<\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/em> the rendering process(we will see a bit later how it is possible) and give the browser the chance to perform other tasks, such as rendering, receiving user input, etc.<\/p>\n<p><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong>How does React yield to the main thread?<\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/p>\n<p>There are a few browser APIs that allow React to achieve that. For example, <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/API\/Window\/setImmediate\" target=\"_blank\" rel=\"noopener\">the documentation<\/a> for <code>window.setImmediate()<\/code> says that:<\/p>\n<blockquote>\n<p>This method is used to break up long running operations and run a callback function immediately after the browser has completed other operations such as events and display updates.<\/p>\n<\/blockquote>\n<p>However, this method is not expected to be implemented in browsers. The good news is that <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/API\/Window\/setImmediate#notes\" target=\"_blank\" rel=\"noopener\">there are alternatives<\/a> that lead to the same result, one of them being the <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/API\/MessageChannel\" target=\"_blank\" rel=\"noopener\"><code>MessageChannel<\/code> API<\/a>.<\/p>\n<p><a href=\"https:\/\/github.com\/facebook\/react\/blob\/v18.2.0\/packages\/scheduler\/src\/forks\/Scheduler.js#L569-L574\" target=\"_blank\" rel=\"noopener\">This is exactly how<\/a> React uses the <code>MessageChannel<\/code> API in order to schedule functions to be run after the browser has performed some of its essential tasks:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-jsx\" data-lang=\"jsx\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">channel<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">new<\/span> <span style=\"color:#a6e22e\">MessageChannel<\/span>();\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">port<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">channel<\/span>.<span style=\"color:#a6e22e\">port2<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">channel<\/span>.<span style=\"color:#a6e22e\">port1<\/span>.<span style=\"color:#a6e22e\">onmessage<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">performWorkUntilDeadline<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">schedulePerformWorkUntilDeadline<\/span> <span style=\"color:#f92672\">=<\/span> () =&gt; {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">port<\/span>.<span style=\"color:#a6e22e\">postMessage<\/span>(<span style=\"color:#66d9ef\">null<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>};\n<\/span><\/span><\/code><\/pre><\/div><p>The scheduling takes place once <code>schedulePerformWorkUntilDeadline()<\/code> is invoked - keep an eye on this function, this will be so important later on!<\/p>\n<p>So, by calling <code>schedulePerformWorkUntilDeadline()<\/code> and after the browser has been granted the necessary time to receive user interaction and to perform other browser-related tasks, <code>performWorkUntilDeadline()<\/code> will be invoked and this is where React-related scheduled tasks will be run. <strong>An example<\/strong> of such tasks, especially relevant for the current situation, is a task that will <strong>render the Virtual DOM tree<\/strong> either synchronously or concurrently.<\/p>\n<p>Now that we have learned about what <em>yielding to the main thread<\/em> means, let\u2019s verify in the next section that <code>startTransition<\/code> does just that.<\/p>\n<h3 id=\"verifying-that-starttransition-indeed-works\">\n  <span>\n  Verifying that startTransition indeed works\n  <\/span>\n  <a href=\"#verifying-that-starttransition-indeed-works\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h3><p>In the previous section, we have seen that <code>schedulePerformWorkUntilDeadline()<\/code> will be invoked in order to schedule some work to be done after browser\u2019s essential tasks - this contributes to a non-freezing experience for the user.<\/p>\n<p>The intuition should now be that <code>startTransition<\/code> will lead to <code>schedulePerformWorkUntilDeadline()<\/code> being called <strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong>periodically<\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong>. As a result, <strong>not all<\/strong> of the <code>SlowPost<\/code> components <strong><strong><strong>should be rendered at once<\/strong><\/strong><\/strong>.<\/p>\n<p><em><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong>How can we assert that?<\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/em><\/p>\n<p>Let\u2019s open the Dev Tools in the <a href=\"https:\/\/codesandbox.io\/s\/objective-ride-qkznlp?file=\/PostsTab.js\" target=\"_blank\" rel=\"noopener\">CodeSandbox application<\/a> and place the following logpoint:<\/p>\n<p><p class=\"markdown-image\">\n  <img src=\"images\/Untitled%202.png\" alt=\"Untitled\"  \/>\n<\/p><\/p>\n<p>A few key points worth noticing:<\/p>\n<ul>\n<li>\n<p>in the leftmost panel, we have added a log that will help us understand when a <code>SlowPost<\/code> component is being rendered<\/p>\n<\/li>\n<li>\n<p>in the rightmost panel, he have added a logpoint to the line 538 of the <code>scheduler.development.js<\/code> file - this will let us know when React <strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong>has interrupted the rendering process<\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong> and <strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong>reschedules it for later<\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong>, after the browser will have performed its other tasks<\/p>\n<\/li>\n<li>\n<p>in the rightmost panel, on line 517, notice how <code>performWorkUntilDeadline()<\/code> calls <code>schedulePerformWorkUntilDeadline()<\/code> which will, in turn, schedule <code>performWorkUntilDeadline()<\/code> via the <code>MessageChannel<\/code> API; here is, once again, how it does that:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-jsx\" data-lang=\"jsx\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">channel<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">new<\/span> <span style=\"color:#a6e22e\">MessageChannel<\/span>();\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">port<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">channel<\/span>.<span style=\"color:#a6e22e\">port2<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">channel<\/span>.<span style=\"color:#a6e22e\">port1<\/span>.<span style=\"color:#a6e22e\">onmessage<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">performWorkUntilDeadline<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">schedulePerformWorkUntilDeadline<\/span> <span style=\"color:#f92672\">=<\/span> () =&gt; {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">port<\/span>.<span style=\"color:#a6e22e\">postMessage<\/span>(<span style=\"color:#66d9ef\">null<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>};\n<\/span><\/span><\/code><\/pre><\/div><p>as you can notice, there is a recursion taking place; this is what ensures that React <strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong>periodically<\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong> yields to the main thread<\/p>\n<\/li>\n<li>\n<p>lastly, still in the rightmost panel, calling <code>scheduledHostCallback<\/code> will lead to (some of the) scheduled tasks being executed<\/p>\n<\/li>\n<\/ul>\n<p>Now, it\u2019s time to see the logs in action. Having the <em>Console<\/em> panel visible, try clicking on <strong><strong><strong><strong>Posts (Slow)<\/strong><\/strong><\/strong><\/strong> tab and then, very quickly, click on the <em><strong><strong><strong><strong><strong>Contact tab<\/strong><\/strong><\/strong><\/strong><\/strong><\/em>. After doing that, something like this should be shown in the console:<\/p>\n<p><p class=\"markdown-image\">\n  <img src=\"images\/Untitled%203.png\" alt=\"Untitled\"  \/>\n<\/p><\/p>\n<p>As you can see, the <code>SlowPosts<\/code> components <strong>won\u2019t be rendered all at once<\/strong>, but in <strong><strong><strong><strong><strong><strong>chunks<\/strong><\/strong><\/strong><\/strong><\/strong><\/strong>, so that the browser has enough time to be responsive to the user.<\/p>\n<p>So, our hypothesis has passed this test! Again, this is due to using <code>startTransition<\/code>.<\/p>\n<p>In the next section, we will visualize this process of <em>performing tasks and yielding to the browser<\/em> with the help of some diagrams. This is also referred to as <em><strong><strong><strong><strong><strong><strong>concurrent rendering.<\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/em><\/p>\n<h2 id=\"visualizing-the-concurrent-rendering-process\">\n  <span>\n  Visualizing the concurrent rendering process\n  <\/span>\n  <a href=\"#visualizing-the-concurrent-rendering-process\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><p>In order to understand the beauty of <strong><strong><strong><strong><strong><strong><strong><strong><strong><strong>concurrent rendering<\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong>, it\u2019s important to first understand how React renders a tree of components.<\/p>\n<p>The React\u2019s <strong>synchronous<\/strong> rendering process roughly looks like this:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-jsx\" data-lang=\"jsx\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">while<\/span> (<span style=\"color:#a6e22e\">workInProgress<\/span> <span style=\"color:#f92672\">!==<\/span> <span style=\"color:#66d9ef\">null<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">performUnitOfWork<\/span>(<span style=\"color:#a6e22e\">workInProgress<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p>where <code>workInProgress<\/code> indicates the current Virtual DOM node under consideration. Calling <code>performUnitOfWork()<\/code> can result, for instance, in rendering a component, if <code>workInProgress<\/code> is currently assigned to a functional component.<\/p>\n<p>Let\u2019s consider the <code>PostsTab<\/code> component in the <a href=\"https:\/\/codesandbox.io\/s\/objective-ride-qkznlp?file=\/PostsTab.js\" target=\"_blank\" rel=\"noopener\">CodeSandbox application<\/a>:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-jsx\" data-lang=\"jsx\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">PostsTab<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">memo<\/span>(<span style=\"color:#66d9ef\">function<\/span> <span style=\"color:#a6e22e\">PostsTab<\/span>() {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">let<\/span> <span style=\"color:#a6e22e\">items<\/span> <span style=\"color:#f92672\">=<\/span> [];\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">for<\/span> (<span style=\"color:#66d9ef\">let<\/span> <span style=\"color:#a6e22e\">i<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#ae81ff\">0<\/span>; <span style=\"color:#a6e22e\">i<\/span> <span style=\"color:#f92672\">&lt;<\/span> <span style=\"color:#ae81ff\">1000<\/span>; <span style=\"color:#a6e22e\">i<\/span><span style=\"color:#f92672\">++<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">items<\/span>.<span style=\"color:#a6e22e\">push<\/span>(&lt;<span style=\"color:#f92672\">SlowPost<\/span> <span style=\"color:#a6e22e\">key<\/span><span style=\"color:#f92672\">=<\/span>{<span style=\"color:#a6e22e\">i<\/span>} <span style=\"color:#a6e22e\">index<\/span><span style=\"color:#f92672\">=<\/span>{<span style=\"color:#a6e22e\">i<\/span>} \/&gt;);\n<\/span><\/span><span style=\"display:flex;\"><span>  }\n<\/span><\/span><span style=\"display:flex;\"><span>  \n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">return<\/span> &lt;<span style=\"color:#f92672\">ul<\/span> <span style=\"color:#a6e22e\">className<\/span><span style=\"color:#f92672\">=<\/span><span style=\"color:#e6db74\">&#34;items&#34;<\/span>&gt;{<span style=\"color:#a6e22e\">items<\/span>}&lt;\/<span style=\"color:#f92672\">ul<\/span>&gt;;\n<\/span><\/span><span style=\"display:flex;\"><span>});\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">function<\/span> <span style=\"color:#a6e22e\">SlowPost<\/span>({ <span style=\"color:#a6e22e\">index<\/span> }) {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">let<\/span> <span style=\"color:#a6e22e\">startTime<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">performance<\/span>.<span style=\"color:#a6e22e\">now<\/span>();\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">while<\/span> (<span style=\"color:#a6e22e\">performance<\/span>.<span style=\"color:#a6e22e\">now<\/span>() <span style=\"color:#f92672\">-<\/span> <span style=\"color:#a6e22e\">startTime<\/span> <span style=\"color:#f92672\">&lt;<\/span> <span style=\"color:#ae81ff\">1<\/span>) { }\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">return<\/span> &lt;<span style=\"color:#f92672\">li<\/span> <span style=\"color:#a6e22e\">className<\/span><span style=\"color:#f92672\">=<\/span><span style=\"color:#e6db74\">&#34;item&#34;<\/span>&gt;<span style=\"color:#a6e22e\">Post<\/span> <span style=\"color:#960050;background-color:#1e0010\">#<\/span>{<span style=\"color:#a6e22e\">index<\/span> <span style=\"color:#f92672\">+<\/span> <span style=\"color:#ae81ff\">1<\/span>}&lt;\/<span style=\"color:#f92672\">li<\/span>&gt;;\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p>Here is how the corresponding Virtual DOM looks like after <code>PostsTab<\/code> has rendered:<\/p>\n<p><p class=\"markdown-image\">\n  <img src=\"images\/Untitled%204.png\" alt=\"Untitled\"  \/>\n<\/p><\/p>\n<blockquote>\n<p>As a result of rendering, <code>PostsTab()<\/code> returned an array of other React elements(which will later be converted into Virtual DOM nodes).<\/p>\n<\/blockquote>\n<p>After that, each of the returned <code>SlowPost<\/code> children will become, one by one, <code>workInProgress<\/code>.<\/p>\n<p>So, firstly, <code>workInProgress = PostsTabNode<\/code>, then <code>performUnitOfWork(workInProgress)<\/code> is called, then <code>workInProgress = SlowPost0Node<\/code>, then <code>performUnitOfWork(workInProgress)<\/code> is invoked(which, in essence, means that is has rendered), then <code>workInProgress = SlowPost1Node<\/code> so on.<\/p>\n<p>When <strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong>rendering concurrently,<\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong> the while loop looks like this:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-jsx\" data-lang=\"jsx\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">while<\/span> (<span style=\"color:#a6e22e\">workInProgress<\/span> <span style=\"color:#f92672\">!==<\/span> <span style=\"color:#66d9ef\">null<\/span> <span style=\"color:#f92672\">&amp;&amp;<\/span> <span style=\"color:#f92672\">!<\/span><span style=\"color:#a6e22e\">shouldYield<\/span>()) {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">performUnitOfWork<\/span>(<span style=\"color:#a6e22e\">workInProgress<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>  } \n<\/span><\/span><\/code><\/pre><\/div><p>Notice the <code>!shouldYield()<\/code> part - this is the part that allows React to <strong>interrupt the rendering process<\/strong> and then <strong>yield to the main thread.<\/strong> This is what\u2019s relevant about <code>shouldYield()<\/code> <a href=\"https:\/\/github.com\/facebook\/react\/blob\/v18.2.0\/packages\/scheduler\/src\/forks\/Scheduler.js#L441-L446\" target=\"_blank\" rel=\"noopener\">implementation<\/a>:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-jsx\" data-lang=\"jsx\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">timeElapsed<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">getCurrentTime<\/span>() <span style=\"color:#f92672\">-<\/span> <span style=\"color:#a6e22e\">startTime<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#a6e22e\">timeElapsed<\/span> <span style=\"color:#f92672\">&lt;<\/span> <span style=\"color:#a6e22e\">frameInterval<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#75715e\">\/\/ The main thread has only been blocked for a really short amount of time;\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>  <span style=\"color:#75715e\">\/\/ smaller than a single frame. Don&#39;t yield yet.\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>  <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#66d9ef\">false<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ ... Some details have been omitted for brevity.\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span><span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#66d9ef\">true<\/span>;\n<\/span><\/span><\/code><\/pre><\/div><p>Put differently, <code>shouldYield()<\/code> it checks if React has spent enough time on rendering and, if that\u2019s the case, allow the browser to perform high priority tasks. If there is still time to render, then it goes on executing <code>performUnitOfWork()<\/code> until the next check of the <strong><strong><strong><strong><strong>while loop<\/strong><\/strong><\/strong><\/strong><\/strong>, where <code>shouldYield()<\/code> will be consulted again.<\/p>\n<p>That\u2019s the essence of <strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong>concurrent rendering.<\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong> Now, let\u2019s visualize the example in question:<\/p>\n<p><p class=\"markdown-image\">\n  <img src=\"images\/Untitled%205.png\" alt=\"Untitled\"  \/>\n<\/p><\/p>\n<p>The above diagram (almost) corresponds to the behavior we have noticed in the console:<\/p>\n<p><p class=\"markdown-image\">\n  <img src=\"images\/Untitled%203.png\" alt=\"Untitled\"  \/>\n<\/p><\/p>\n<p>Let\u2019s recap what\u2019s going on: React renders the component tree by traversing it. The current node that is being <strong>visited<\/strong>(and about to be rendered) is <strong>denoted<\/strong> by <code>workInProgress<\/code>. The traversal takes place in a <em>while loop<\/em> which means that, before going ahead and performing work(e.g. rendering) on a <code>workInProgress<\/code> node, it will check if it should yield to the main thread first(i.e. denoted by the <code>shoudlYield()<\/code> function).\nWhen it\u2019s time to yield, the <strong><strong><strong><strong><strong>while loop<\/strong><\/strong><\/strong><\/strong><\/strong> will <strong>stop<\/strong> and a task will be scheduled to run after the browser has done some work, while making sure the reference to the current <code>workInProgress<\/code> <strong>will be kept<\/strong> for the next time the rendering will be resumed.\nWhen there is still time to render, <code>performUnitOfWork(workInProgress)<\/code> will be invoked and, after that, <code>workInProgress<\/code> will be assigned to the next Virtual DOM node that will have to be traversed.<\/p>\n<p>At this point, we should have at least a slightly better understanding of how <strong><strong><strong><strong><strong><strong><strong><strong><strong><strong>concurrent rendering<\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong> works. But, <strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong>there is still something missing<\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong> - <em>how does <code>startTransition<\/code> activate concurrent rendering?<\/em> The short answer is that, when the function is invoked, some flags end up to be added to the <strong><strong>root<\/strong><\/strong> node and these flags instruct React that this tree can be rendered in <em><strong><strong><strong><strong><strong><strong><strong>concurrent mode<\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/em>.<\/p>\n<p>In the next section we will see why <strong>concurrent mode is not enough<\/strong> if the work is not properly divided in smaller chunks.<\/p>\n<h2 id=\"expensive-tasks-should-be-divided-into-components-in-order-for-transitions-to-work-properly\">\n  <span>\n  Expensive tasks should be divided into components in order for transitions to work properly\n  <\/span>\n  <a href=\"#expensive-tasks-should-be-divided-into-components-in-order-for-transitions-to-work-properly\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><p>Here is <a href=\"https:\/\/codesandbox.io\/s\/react-transition-not-working-6fj7jj?file=\/PostsTab.js\" target=\"_blank\" rel=\"noopener\">a CodeSandbox application<\/a> that illustrates an example where <code>startTransition<\/code> becomes useless:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-jsx\" data-lang=\"jsx\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">PostsTab<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">memo<\/span>(<span style=\"color:#66d9ef\">function<\/span> <span style=\"color:#a6e22e\">PostsTab<\/span>() {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">let<\/span> <span style=\"color:#a6e22e\">items<\/span> <span style=\"color:#f92672\">=<\/span> [];\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#75715e\">\/\/ The page should now be unresponsive for 4 seconds.\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>  <span style=\"color:#66d9ef\">for<\/span> (<span style=\"color:#66d9ef\">let<\/span> <span style=\"color:#a6e22e\">i<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#ae81ff\">0<\/span>; <span style=\"color:#a6e22e\">i<\/span> <span style=\"color:#f92672\">&lt;<\/span> <span style=\"color:#ae81ff\">4000<\/span>; <span style=\"color:#a6e22e\">i<\/span><span style=\"color:#f92672\">++<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#75715e\">\/\/ No longer dividing the task in smaller ones!\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>\t\t<span style=\"color:#75715e\">\/\/ items.push(&lt;SlowPost key={i} index={i} \/&gt;);\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">let<\/span> <span style=\"color:#a6e22e\">startTime<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">performance<\/span>.<span style=\"color:#a6e22e\">now<\/span>();\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">while<\/span> (<span style=\"color:#a6e22e\">performance<\/span>.<span style=\"color:#a6e22e\">now<\/span>() <span style=\"color:#f92672\">-<\/span> <span style=\"color:#a6e22e\">startTime<\/span> <span style=\"color:#f92672\">&lt;<\/span> <span style=\"color:#ae81ff\">1<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#75715e\">\/\/ Do nothing for 1 ms per item to emulate extremely slow code\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>    }\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">items<\/span>.<span style=\"color:#a6e22e\">push<\/span>(&lt;<span style=\"color:#f92672\">li<\/span> <span style=\"color:#a6e22e\">className<\/span><span style=\"color:#f92672\">=<\/span><span style=\"color:#e6db74\">&#34;item&#34;<\/span>&gt;<span style=\"color:#a6e22e\">Post<\/span> <span style=\"color:#960050;background-color:#1e0010\">#<\/span>{<span style=\"color:#a6e22e\">i<\/span> <span style=\"color:#f92672\">+<\/span> <span style=\"color:#ae81ff\">1<\/span>}&lt;\/<span style=\"color:#f92672\">li<\/span>&gt;);\n<\/span><\/span><span style=\"display:flex;\"><span>  }\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">return<\/span> &lt;<span style=\"color:#f92672\">ul<\/span> <span style=\"color:#a6e22e\">className<\/span><span style=\"color:#f92672\">=<\/span><span style=\"color:#e6db74\">&#34;items&#34;<\/span>&gt;{<span style=\"color:#a6e22e\">items<\/span>}&lt;\/<span style=\"color:#f92672\">ul<\/span>&gt;;\n<\/span><\/span><span style=\"display:flex;\"><span>});\n<\/span><\/span><\/code><\/pre><\/div><p>Although this is a contrived example, it should demonstrate that setting the state inside a <code>startTransition<\/code> callback<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-jsx\" data-lang=\"jsx\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">function<\/span> <span style=\"color:#a6e22e\">selectTab<\/span>(<span style=\"color:#a6e22e\">nextTab<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">startTransition<\/span>(() =&gt; {\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#a6e22e\">setTab<\/span>(<span style=\"color:#a6e22e\">nextTab<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>    });\n<\/span><\/span><span style=\"display:flex;\"><span>  }\n<\/span><\/span><\/code><\/pre><\/div><p>has no effect whatsoever. Clicking on the <strong><strong><strong><strong>Posts (slow) tab<\/strong><\/strong><\/strong><\/strong> will cause the web page to <strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong>become unresponsive<\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong> and, as a result, clicking on <em><strong><strong><strong>Contact<\/strong><\/strong><\/strong><\/em> will have an effect only after 4 seconds(i.e. the required time for <code>PostsTab<\/code> to render).<\/p>\n<p><em>Why does it happen, although <code>startTransition<\/code> has been used?<\/em><\/p>\n<p>The initial problem was that <strong>multiple smaller tasks<\/strong> that took 1 millisecond each would be rendered synchronously(the total rendering time being <em><strong>1ms * numberOfSmallerTasks<\/strong><\/em>). The problem was solved by <code>startTransition<\/code> because it was able to interrupt the tree traversal(and, as a result, the rendering process) so that the browser can work on high priority tasks. <strong>Now, the problem is<\/strong> <strong><strong><strong><strong>that one single task takes 4 seconds<\/strong><\/strong><\/strong><\/strong>. Basically, the concurrent mode is useless because one single unit takes literally too much time. The concurrent mode relies on the fact that there are multiple <code>workInProgress<\/code> nodes that need to be traversed.<\/p>\n<p>In the initial example, there were 1000 <code>workInProgress<\/code> <code>SlowPost<\/code> components - they could easily be divided into batches of, let\u2019s say, 5 <code>SlowPost<\/code> components, meaning that such batch would take 5 milliseconds. After one batch, it\u2019s the browser\u2019s turn to work on other tasks, then, again, another batch awaits and this keeps on repeating until there is nothing else to render.<\/p>\n<h2 id=\"conclusion\">\n  <span>\n  Conclusion\n  <\/span>\n  <a href=\"#conclusion\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><p>I truly hope this was a useful (and fun) learning journey.<\/p>\n<p>Lastly, I think this a great way to learn: create an hypothesis in your mind(e.g. <em><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong>this works this way because of these reasons\u2026<\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/em>), keep pondering it and then finally pursue the answer.<\/p>\n<p>Thanks for reading!<\/p>\n<h2 id=\"references\">\n  <span>\n  References\n  <\/span>\n  <a href=\"#references\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><ul>\n<li><a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/JavaScript\/Event_loop\" target=\"_blank\" rel=\"noopener\">https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/JavaScript\/Event_loop<\/a><\/li>\n<li><a href=\"https:\/\/www.webperf.tips\/tip\/event-loop\/#:~:text=The%20Event%20Loop%2C%20by%20design,to%20do%20an%20asynchronous%20task%3F\" target=\"_blank\" rel=\"noopener\">https:\/\/www.webperf.tips\/tip\/event-loop\/#:~:text=The Event Loop%2C by design,to do an asynchronous task%3F<\/a><\/li>\n<li><a href=\"https:\/\/web.dev\/rail\/\" target=\"_blank\" rel=\"noopener\">https:\/\/web.dev\/rail\/<\/a><\/li>\n<li><a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/API\/MessageChannel\" target=\"_blank\" rel=\"noopener\">https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/API\/MessageChannel<\/a><\/li>\n<\/ul>\n"},{"title":"On React Suspense\u2019s throttling","link":"https:\/\/andreigatej.dev\/blog\/on-react-suspense-throttling\/","pubDate":"Sun, 13 Aug 2023 21:28:47 +0300","guid":"https:\/\/andreigatej.dev\/blog\/on-react-suspense-throttling\/","description":"<!-- raw HTML omitted -->\n<h2 id=\"introduction\">\n  <span>\n  Introduction\n  <\/span>\n  <a href=\"#introduction\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><p>I have to admit, the title sounds a bit ambiguous. But, the idea of this article came to mind after I have stumbled across a very interesting test case for the React\u2019s <code>Suspense<\/code> component. I thought it was something definitely worth sharing.<\/p>\n<p><em><strong><strong>Throttling<\/strong><\/strong><\/em> can be taken into account when we consider <strong><strong><strong><strong><strong><strong><strong>nested<\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong> <code>Suspense<\/code> components. What is actually meant by <strong><strong><strong><strong><strong>throttling<\/strong><\/strong><\/strong><\/strong><\/strong> is <strong><strong><strong><strong>delaying<\/strong><\/strong><\/strong><\/strong> showing the <strong>fallback component<\/strong> of a nested <code>Suspense<\/code> component <strong>immediately after<\/strong> its parent <code>Suspense<\/code> component has stopped suspending. This will make more sense by the end of this article.<\/p>\n<p>We will first cover some basics of the <code>Suspense<\/code> component, then we will move to the interesting bits of this article.<\/p>\n<blockquote>\n<p>For the record, the test case this article is based on is called <em><a href=\"https:\/\/github.com\/facebook\/react\/blob\/main\/packages\/react-reconciler\/src\/__tests__\/ReactSuspense-test.internal.js#L292C7-L292C57\" target=\"_blank\" rel=\"noopener\">does not throttle fallback committing for too long<\/a>.<\/em><\/p>\n<\/blockquote>\n<p>Let\u2019s get started!<\/p>\n<h2 id=\"why-do-suspended-components-throw-errors\">\n  <span>\n  Why do Suspended components throw errors?\n  <\/span>\n  <a href=\"#why-do-suspended-components-throw-errors\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><p>There answer is that <code>Suspense<\/code> mimics the behavior of <a href=\"https:\/\/react.dev\/reference\/react\/Component#catching-rendering-errors-with-an-error-boundary\" target=\"_blank\" rel=\"noopener\">error boundaries<\/a>.<\/p>\n<p>In order to understand how the <code>Suspense<\/code> component works, we will essentially have to understand how error boundaries work. So, surprisingly, we will solve two problems at once, which doesn\u2019t sound quite bad.<\/p>\n<p>In the next section, we will quickly touch on the fundamentals of the <code>Suspense<\/code> component.<\/p>\n<h2 id=\"a-basic-example-of-a-suspense-component\">\n  <span>\n  A basic example of a Suspense component\n  <\/span>\n  <a href=\"#a-basic-example-of-a-suspense-component\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><p>This is the example we\u2019re going to use throughout this section:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-jsx\" data-lang=\"jsx\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">function<\/span> <span style=\"color:#a6e22e\">Bar<\/span>(<span style=\"color:#a6e22e\">props<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#a6e22e\">props<\/span>.<span style=\"color:#a6e22e\">children<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">function<\/span> <span style=\"color:#a6e22e\">AsyncText<\/span>({<span style=\"color:#a6e22e\">text<\/span>}) {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#75715e\">\/\/ `readText()` will trigger the `&lt;Suspense \/&gt;` component.\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>\t\t<span style=\"color:#a6e22e\">readText<\/span>(<span style=\"color:#a6e22e\">text<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>\t\t<span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#a6e22e\">text<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">function<\/span> <span style=\"color:#a6e22e\">Text<\/span>({<span style=\"color:#a6e22e\">text<\/span>}) {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#a6e22e\">text<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ ==================================\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">function<\/span> <span style=\"color:#a6e22e\">App<\/span> () {\n<\/span><\/span><span style=\"display:flex;\"><span>\t&lt;<span style=\"color:#f92672\">Suspense<\/span> <span style=\"color:#a6e22e\">fallback<\/span><span style=\"color:#f92672\">=<\/span>{&lt;<span style=\"color:#f92672\">Text<\/span> <span style=\"color:#a6e22e\">text<\/span><span style=\"color:#f92672\">=<\/span><span style=\"color:#e6db74\">&#34;Loading...&#34;<\/span> \/&gt;}&gt;\n<\/span><\/span><span style=\"display:flex;\"><span>\t\t&lt;<span style=\"color:#f92672\">Bar<\/span>&gt;\n<\/span><\/span><span style=\"display:flex;\"><span>      &lt;<span style=\"color:#f92672\">AsyncText<\/span> <span style=\"color:#a6e22e\">text<\/span><span style=\"color:#f92672\">=<\/span><span style=\"color:#e6db74\">&#34;A&#34;<\/span> \/&gt;\n<\/span><\/span><span style=\"display:flex;\"><span>      &lt;<span style=\"color:#f92672\">Text<\/span> <span style=\"color:#a6e22e\">text<\/span><span style=\"color:#f92672\">=<\/span><span style=\"color:#e6db74\">&#34;B&#34;<\/span> \/&gt;\n<\/span><\/span><span style=\"display:flex;\"><span>    &lt;\/<span style=\"color:#f92672\">Bar<\/span>&gt;\n<\/span><\/span><span style=\"display:flex;\"><span>\t&lt;\/<span style=\"color:#f92672\">Suspense<\/span>&gt;\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><blockquote>\n<p>The above example is heavily inspired by <a href=\"https:\/\/github.com\/facebook\/react\/blob\/v18.2.0\/packages\/react-reconciler\/src\/__tests__\/ReactSuspense-test.internal.js\" target=\"_blank\" rel=\"noopener\">React\u2019s Suspense test suite<\/a>.<\/p>\n<\/blockquote>\n<p>In the snippet above, <code>AsyncText<\/code> will be responsible for fetching data and, as a result, for making the <code>Suspense<\/code> component show the <code>fallback<\/code> component declared as a prop. For the purpose of simplicity, we are not going to focus on <code>&lt;AsyncText \/&gt;<\/code>&rsquo;s <code>readText()<\/code> function - it suffices to know that the function will <strong>throw<\/strong> <strong>a promise<\/strong> the first time it is invoked and, while the data is fetched(i.e. during the <strong><strong><strong><strong>pending<\/strong><\/strong><\/strong><\/strong> state), the <code>Suspense<\/code>&rsquo;s <code>fallback<\/code> component will be shown. When the data has arrived, React will know when to <strong><strong>stop<\/strong><\/strong> showing the <code>fallback<\/code> component and render the subtree whose root is the <code>&lt;Bar \/&gt;<\/code> component.<\/p>\n<p>The component hierarchy can be visualized this way:<\/p>\n<p><p class=\"markdown-image\">\n  <img src=\"images\/Untitled.png\" alt=\"Untitled\"  \/>\n<\/p><\/p>\n<blockquote>\n<p>The <code>AsyncText<\/code> and <code>Text<\/code> components are placed this way(on the same row and only one arrow connecting them) because this resembles the actual way React structures Virtual DOM nodes. In this case, they are <strong><strong><strong><strong><strong>sibling components<\/strong><\/strong><\/strong><\/strong><\/strong>. More about the React\u2019s Virtual DOM implementation can be <a href=\"https:\/\/indepth.dev\/posts\/1501\/exploring-how-virtual-dom-is-implemented-in-react\" target=\"_blank\" rel=\"noopener\">found here<\/a>.<\/p>\n<\/blockquote>\n<p>Notice how we have delimited the <code>Suspense<\/code>&rsquo;s subtree in blue.<\/p>\n<p>Now, on the first render, when the <code>AsyncText<\/code> component will be rendered, the <code>readText()<\/code> function will inevitably be invoked. When that happens, that function will <strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong>throw a promise<\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong>. What happens next is that React <strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong>will temporarily stop the rendering process<\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong> because it has to <strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong>find the closest<\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong> <code>Suspense<\/code> component relative to the <code>AsyncText<\/code> component. In this case, it\u2019s obvious which <code>Suspense<\/code> component will be chosen:<\/p>\n<p><p class=\"markdown-image\">\n  <img src=\"images\/Untitled%201.png\" alt=\"Untitled\"  \/>\n<\/p><\/p>\n<p>At this point, once the closest <code>Suspense<\/code> component has been found, that component must render the provided <code>fallback<\/code> component and basically <strong><strong><strong><strong><strong><strong><strong><strong>suspend<\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong> its content.<\/p>\n<p>In the next section, we will see how React handles nested <code>Suspense<\/code> components.<\/p>\n<h2 id=\"nested-suspense-components\">\n  <span>\n  Nested Suspense components\n  <\/span>\n  <a href=\"#nested-suspense-components\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><p>Our example for this section looks like this:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-jsx\" data-lang=\"jsx\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">function<\/span> <span style=\"color:#a6e22e\">AsyncText<\/span>({<span style=\"color:#a6e22e\">text<\/span>}) {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#75715e\">\/\/ `readText()` will trigger the `&lt;Suspense \/&gt;` component.\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>\t\t<span style=\"color:#a6e22e\">readText<\/span>(<span style=\"color:#a6e22e\">text<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>\t\t<span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#a6e22e\">text<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">function<\/span> <span style=\"color:#a6e22e\">Text<\/span>({<span style=\"color:#a6e22e\">text<\/span>}) {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#a6e22e\">text<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ ================================\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">function<\/span> <span style=\"color:#a6e22e\">App<\/span>() {\n<\/span><\/span><span style=\"display:flex;\"><span>\t<span style=\"color:#66d9ef\">return<\/span> (\n<\/span><\/span><span style=\"display:flex;\"><span>\t  &lt;<span style=\"color:#f92672\">Suspense<\/span> <span style=\"color:#a6e22e\">fallback<\/span><span style=\"color:#f92672\">=<\/span>{&lt;<span style=\"color:#f92672\">Text<\/span> <span style=\"color:#a6e22e\">text<\/span><span style=\"color:#f92672\">=<\/span><span style=\"color:#e6db74\">&#34;Loading...&#34;<\/span> \/&gt;}&gt;\n<\/span><\/span><span style=\"display:flex;\"><span>\t    &lt;<span style=\"color:#f92672\">AsyncText<\/span> <span style=\"color:#a6e22e\">text<\/span><span style=\"color:#f92672\">=<\/span><span style=\"color:#e6db74\">&#34;A&#34;<\/span> \/&gt;\n<\/span><\/span><span style=\"display:flex;\"><span>\t    &lt;<span style=\"color:#f92672\">Suspense<\/span> <span style=\"color:#a6e22e\">fallback<\/span><span style=\"color:#f92672\">=<\/span>{&lt;<span style=\"color:#f92672\">Text<\/span> <span style=\"color:#a6e22e\">text<\/span><span style=\"color:#f92672\">=<\/span><span style=\"color:#e6db74\">&#34;Loading more...&#34;<\/span> \/&gt;}&gt;\n<\/span><\/span><span style=\"display:flex;\"><span>\t      &lt;<span style=\"color:#f92672\">AsyncText<\/span> <span style=\"color:#a6e22e\">text<\/span><span style=\"color:#f92672\">=<\/span><span style=\"color:#e6db74\">&#34;B&#34;<\/span> \/&gt;\n<\/span><\/span><span style=\"display:flex;\"><span>\t    &lt;\/<span style=\"color:#f92672\">Suspense<\/span>&gt;\n<\/span><\/span><span style=\"display:flex;\"><span>\t  &lt;\/<span style=\"color:#f92672\">Suspense<\/span>&gt;\n<\/span><\/span><span style=\"display:flex;\"><span>\t);\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p>And here is the corresponding diagram:<\/p>\n<p><p class=\"markdown-image\">\n  <img src=\"images\/Untitled%202.png\" alt=\"Untitled\"  \/>\n<\/p><\/p>\n<blockquote>\n<p>The above example is heavily inspired by <a href=\"https:\/\/github.com\/facebook\/react\/blob\/v18.2.0\/packages\/react-reconciler\/src\/__tests__\/ReactSuspense-test.internal.js\" target=\"_blank\" rel=\"noopener\">React\u2019s <code>&lt;Suspense \/&gt;<\/code> test suite<\/a>.<\/p>\n<\/blockquote>\n<p>Notice how the two <code>Suspense<\/code> subtrees are colored in blue and green, respectively.<\/p>\n<p>Before going any further, there is an interesting question I\u2019d like you to ponder a bit: <em>which <code>Suspense<\/code> subtree will <strong>suspend first<\/strong><\/em>? The blue one or the green one?*<\/p>\n<p>Firstly, we can all agree that the <strong><strong>App<\/strong><\/strong> component will render first. Then, its single <code>Suspense<\/code> child will render. Then, since the the <em>AsyncText A component<\/em> will have to render first(because it\u2019s the first child), its rendering will cause <strong><strong><strong><strong><strong>a promise to thrown<\/strong><\/strong><\/strong><\/strong><\/strong>(due to the <code>readText()<\/code> function) and, as a result, the <em>blue<\/em> <code>Suspense<\/code> will suspend first. The <em><strong><strong>green<\/strong><\/strong><\/em> one won\u2019t even be reached because the fallback will be shown:<\/p>\n<p><p class=\"markdown-image\">\n  <img src=\"images\/Untitled%203.png\" alt=\"Untitled\"  \/>\n<\/p><\/p>\n<p><em>What happens after <code>readText('A')<\/code> resolves?<\/em><\/p>\n<p>The answer is that the <strong>rendering process will continue<\/strong> from where it left off: the <strong><strong>blue<\/strong><\/strong> <code>Suspense<\/code> component. Now, when the <em><strong><strong>AsyncText A<\/strong><\/strong><\/em> component is rendered, its <code>renderText('A')<\/code> function <strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong>will no longer throw<\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong> - it will act normally. So, this means the rendering process can continue, the next rendered component being the <em><strong><strong>green<\/strong><\/strong><\/em> <code>Suspense<\/code>.<\/p>\n<p>When the <strong><strong><strong><strong><strong><strong>AsyncText B<\/strong><\/strong><\/strong><\/strong><\/strong><\/strong> component is reached, its <code>readText('B')<\/code> will <strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong>throw a promise<\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong> and, then, it will be caught by its closest <code>Suspense<\/code> wrapper - in this case, the <em><strong><strong>green<\/strong><\/strong><\/em> one.<\/p>\n<p><strong><strong><strong><strong><strong><strong>Now, we have reached the interesting part - the throttling<\/strong><\/strong><\/strong><\/strong><\/strong><\/strong>.<\/p>\n<p><em>What will be throttled\/delayed?<\/em><\/p>\n<p>Since a subtree(i.e. the <em>green<\/em> one) has been <strong><strong><strong><strong><strong><strong><strong><strong><strong>suspended<\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong> as a result of <strong>resuming<\/strong> the rendering of the <em><strong><strong>blue<\/strong><\/strong><\/em> <code>Suspense<\/code>, React <strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong>will not commit the new changes to the DOM immediately<\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong>. By <em>new changes<\/em>, we mean showing the fallback component of the <em><strong><strong>green<\/strong><\/strong><\/em> <code>Suspense<\/code>. It\u2019s true that React will actually <strong><strong><strong><strong><strong><strong>render<\/strong><\/strong><\/strong><\/strong><\/strong><\/strong> or, in other words, will determine what the new changes are, but, once again, it will not commit them to the DOM. This is how the <strong><strong><strong><strong>not-committed-yet-to-the-DOM<\/strong><\/strong><\/strong><\/strong> Virtual DOM looks like after the <strong><strong><strong>green<\/strong><\/strong><\/strong> <code>Suspense<\/code> has caught the promise thrown from the <strong><strong><strong>AsyncText B<\/strong><\/strong><\/strong> component:<\/p>\n<p><p class=\"markdown-image\">\n  <img src=\"images\/Untitled%204.png\" alt=\"Untitled\"  \/>\n<\/p><\/p>\n<p>While one would expect the web page to now show the content of <em><strong><strong><strong><strong><strong>AsyncText A<\/strong><\/strong><\/strong><\/strong><\/strong><\/em> <strong>and<\/strong> the content of <strong><strong><strong>green<\/strong><\/strong><\/strong> <code>Suspense<\/code>&rsquo;s <strong><strong><strong><strong><strong><strong><strong><strong><strong>fallback<\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong> component, <strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong>this will not happen immediately.<\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/p>\n<p>In fact, this is the what the browser shows:<\/p>\n<p><p class=\"markdown-image\">\n  <img src=\"images\/Untitled%203.png\" alt=\"Untitled\"  \/>\n<\/p><\/p>\n<p>So, it shows the content that was shown before the <strong>AsyncText A<\/strong>\u2019s data has arrived.<\/p>\n<p><em>For how long?<\/em><\/p>\n<p>Definitely not for too much. The exact number depends on the timestamp of the moment a <strong><strong><strong><strong>fallback<\/strong><\/strong><\/strong><\/strong> has been shown, plus a constant number of milliseconds.<\/p>\n<p>A pseudo-code of what React does would look like this:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-jsx\" data-lang=\"jsx\"><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">setTimeout<\/span>(() =&gt; {\n<\/span><\/span><span style=\"display:flex;\"><span>\t<span style=\"color:#a6e22e\">commitRoot<\/span>();\n<\/span><\/span><span style=\"display:flex;\"><span>}, <span style=\"color:#a6e22e\">msUntilTimeout<\/span>);\n<\/span><\/span><\/code><\/pre><\/div><p><em>But why does it do that?<\/em> From my understanding, it does that in order to not perform a redundant commit operation to the actual DOM in case the data arrives very quickly(let\u2019s say, in less than 300ms).<\/p>\n<p>At this point, the <strong><strong>blue<\/strong><\/strong> <code>Suspense<\/code> component\u2019s <strong><strong><strong><strong>fallback<\/strong><\/strong><\/strong><\/strong> is shown and a commit operation to the real DOM has been scheduled at a later point in time. From here, two things can happen:<\/p>\n<ul>\n<li>\n<p>the data in <em><strong><strong><strong><strong><strong>AsyncText B<\/strong><\/strong><\/strong><\/strong><\/strong><\/em> has not been fetched in less than <code>msUntilTimeout<\/code>; in this case, these changes will finally be committed to the DOM:<\/p>\n<p><p class=\"markdown-image\">\n  <img src=\"images\/Untitled%204.png\" alt=\"Untitled\"  \/>\n<\/p><\/p>\n<p>So, the browser will show whatever the <strong><strong>AsyncText A<\/strong><\/strong> component renders and the content of the <em><strong><strong>green<\/strong><\/strong><\/em> <code>Suspense<\/code>&rsquo;s <em><strong><strong>fallback<\/strong><\/strong><\/em> component.<\/p>\n<\/li>\n<li>\n<p>the data in <em><strong><strong><strong><strong><strong>AsyncText B<\/strong><\/strong><\/strong><\/strong><\/strong><\/em> arrives in time(before the timeout expires) and this is what the browser will show:<\/p>\n<p><p class=\"markdown-image\">\n  <img src=\"images\/Untitled%205.png\" alt=\"Untitled\"  \/>\n<\/p><\/p>\n<\/li>\n<\/ul>\n<p><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong>Keep in mind that<\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong>, until either one of the above situations materialize, the browser will show the <em>blue<\/em> <code>Suspense<\/code>&rsquo;s fallback* component. This is what was meant by <em><strong><strong><strong><strong><strong>throttling<\/strong><\/strong><\/strong><\/strong><\/strong><\/em> - delay showing the <em><strong><strong>green<\/strong><\/strong><\/em> <code>Suspense<\/code>&rsquo;s <em>fallback<\/em> too soon, because data might arrive very quickly and <strong>committing its corresponding fallback<\/strong> to the DOM becomes <strong>redundant<\/strong>, because React will have to commit to the DOM <strong><strong><strong><strong><strong><strong><strong><strong><strong><strong>once again<\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong> immediately after, after the data has arrived.<\/p>\n<h2 id=\"conclusion\">\n  <span>\n  Conclusion\n  <\/span>\n  <a href=\"#conclusion\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><p>I hope this article was able to share some insights about how React\u2019s <code>Suspense<\/code> work.<\/p>\n<p>Lastly, if you\u2019d like to start you own journey exploring React, I\u2019d kindly suggest checking out <a href=\"https:\/\/andreigatej.dev\/blog\/react-debugging-the-source-code\/\" target=\"_blank\" rel=\"noopener\">React: how to debug the source code<\/a>.<\/p>\n<p>Thanks for reading!<\/p>\n<p><em>The diagrams have been created with <a href=\"https:\/\/excalidraw.com\/\" target=\"_blank\" rel=\"noopener\">Excalidraw<\/a>.<\/em><\/p>\n"},{"title":"React: beyond useEffect","link":"https:\/\/andreigatej.dev\/blog\/react-beyond-useeffect\/","pubDate":"Tue, 08 Aug 2023 13:55:58 +0300","guid":"https:\/\/andreigatej.dev\/blog\/react-beyond-useeffect\/","description":"<h2 id=\"introduction\">\n  <span>\n  Introduction\n  <\/span>\n  <a href=\"#introduction\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><p>A while ago, I wrote an article about how <a href=\"https:\/\/indepth.dev\/posts\/1501\/exploring-how-virtual-dom-is-implemented-in-react\" target=\"_blank\" rel=\"noopener\">Virtual DOM is implemented in React<\/a>. In this article, we are going to continue our journey onto <em>how React works under the hood<\/em>(sounds like a good name for a journey, right?) by exploring a special aspect of <code>useEffect()<\/code>, namely when effects are scheduled to be run.<\/p>\n<p>Although the article linked previously is not necessary in order to get the most out of this article, it is worth checking it out - it will help you get a better overall understanding of React and will most likely ease the process of exploring it further. <a href=\"https:\/\/indepth.dev\/posts\/1501\/exploring-how-virtual-dom-is-implemented-in-react\" target=\"_blank\" rel=\"noopener\">Here<\/a> is once again the link to it.<\/p>\n<p>Lastly, if you\u2019d like to embark on this React journey, I have written an article that describes a way to explore React by debugging its tests - <a href=\"https:\/\/andreigatej.dev\/blog\/react-debugging-the-source-code\/\" target=\"_blank\" rel=\"noopener\">React: how to debug the source code<\/a><em>.<\/em><\/p>\n<p>Let\u2019s get started!<\/p>\n<h2 id=\"a-quick-note-on-what-hooks-really-are\">\n  <span>\n  A quick note on what hooks really are\n  <\/span>\n  <a href=\"#a-quick-note-on-what-hooks-really-are\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><p>Having in mind that Virtual DOM nodes(also known as <code>FiberNode<\/code>s in React\u2019s implementation of VDOM) are, in essence, JavaScript objects with certain properties, hooks can also thought as being among these <em><strong><strong><strong>special<\/strong><\/strong><\/strong><\/em> properties.<\/p>\n<p>It\u2019s irrelevant to mention the exact properties - the gist is that React keeps track of hooks with the help of a <strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong>linked list<\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong>. This entails that hooks must be called in a <strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong>strict order<\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong> upon subsequent re-renders and this is also part of the reason(if not the entire reason itself) as to why one can\u2019t call hooks conditionally.<\/p>\n<p>Here\u2019s a quick illustration that might help:<\/p>\n<p><p class=\"markdown-image\">\n  <img src=\"images\/effect-order.png\" alt=\"effects-order\"  \/>\n<\/p><\/p>\n<p><em><a href=\"https:\/\/excalidraw.com\/#json=b5v3CBUltfQCG3_KufXQ8,wPP7MQ-SG50RAMz6quBJZQ\" target=\"_blank\" rel=\"noopener\">Link for the above diagram.<\/a><\/em><\/p>\n<blockquote>\n<p>Note: <code>hooks<\/code> is <strong>not<\/strong> the actual property that is responsible for keeping track of hooks. It\u2019s there just for simplicity\u2019s sake.<\/p>\n<\/blockquote>\n<p>When it comes to the <code>useEffect<\/code> hook, it requires an additional property in order to be able to queue the <em><strong><strong><strong>effects<\/strong><\/strong><\/strong><\/em> need to be called at a certain point. Again, the actual name of the property is irrelevant, but it\u2019s important to know that it exists.<\/p>\n<p>In the next section, we are going to reiterate some well-known aspects of <code>useEffect<\/code>, just to recap.<\/p>\n<h2 id=\"what-you-might-already-know-about-useeffect\">\n  <span>\n  What you might already know about <code>useEffect<\/code>\n  <\/span>\n  <a href=\"#what-you-might-already-know-about-useeffect\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><p>You might already have a basic idea of how <code>useEffect<\/code> works. If not, a quick Google search will reveal the gist of it: it allows you to run some logic <strong>after the browser has (re-)rendered<\/strong>.<\/p>\n<p>Usually, developers don\u2019t need to know more than that in order to be productive. I myself didn\u2019t worry too much about what\u2019s going on under the hood in the beginning. However, there is a question that keep on <em>bothering<\/em> me for a while: <strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong>how does React know to schedule a task(i.e. a piece of code to be executed) after the browser finishes re-rendering?<\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/p>\n<p>Or, put differently, <em>how can one schedule a task to be run after a browser\u2019s rendering tasks?<\/em><\/p>\n<blockquote>\n<p><em>Rendering tasks<\/em> are tasks like determining the coordinates of elements, painting pixels on the screen and properly positioning elements on the <em>Z<\/em> axis. A visualization of these tasks, which are part of the browser\u2019s rendering pipeline, can be found <a href=\"https:\/\/web.dev\/rendering-performance\/#the-pixel-pipeline\" target=\"_blank\" rel=\"noopener\">here<\/a>.<\/p>\n<\/blockquote>\n<p>We are going to answer this question in the next section.<\/p>\n<h2 id=\"whats-more-to-know-about-useeffect\">\n  <span>\n  What\u2019s more to know about <code>useEffect<\/code>\n  <\/span>\n  <a href=\"#whats-more-to-know-about-useeffect\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><p>Whenever a component uses <code>useEffect<\/code>, its corresponding <code>FiberNode<\/code> will be flagged accordingly. Such flags are set during the <em><strong><strong><strong>render<\/strong><\/strong><\/strong><\/em> phase and they are useful during the <em><strong><strong><strong>commit<\/strong><\/strong><\/strong><\/em> phase. The latter phase also represents the moment when React will <strong><strong><strong><strong><strong><strong><strong><strong>schedule<\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong> the action of running all the effects.<\/p>\n<p>The way React ensures that effects are run <strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong>after the browser finishes rendering<\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong> is by using the <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/API\/MessageChannel\" target=\"_blank\" rel=\"noopener\">MessageChannel API<\/a>. If the name of the API does not seem intuitive for the current situation is because it really isn\u2019t. In fact, this API is most likely to be used as a means to communicate between browser threads.<\/p>\n<p><a href=\"https:\/\/github.com\/facebook\/react\/blob\/v18.2.0\/packages\/scheduler\/src\/forks\/Scheduler.js#L569-L574\" target=\"_blank\" rel=\"noopener\">This is how<\/a> React makes use of the <code>MessageChannel<\/code> API to schedule tasks:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-jsx\" data-lang=\"jsx\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">channel<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">new<\/span> <span style=\"color:#a6e22e\">MessageChannel<\/span>();\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">port<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">channel<\/span>.<span style=\"color:#a6e22e\">port2<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">channel<\/span>.<span style=\"color:#a6e22e\">port1<\/span>.<span style=\"color:#a6e22e\">onmessage<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">performWorkUntilDeadline<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">schedulePerformWorkUntilDeadline<\/span> <span style=\"color:#f92672\">=<\/span> () =&gt; {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">port<\/span>.<span style=\"color:#a6e22e\">postMessage<\/span>(<span style=\"color:#66d9ef\">null<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>};\n<\/span><\/span><\/code><\/pre><\/div><ul>\n<li><code>performWorkUntilDeadline()<\/code> is where scheduled tasks(among which can be the one responsible for running the registered effects) are being processed based on their priorities<\/li>\n<li><code>schedulePerformWorkUntilDeadline()<\/code> is the function that, when invoked, <strong><strong><strong><strong><strong><strong><strong><strong>will schedule<\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong> <code>performWorkUntilDeadline()<\/code> to be executed <strong>after the browser finishes rendering<\/strong><\/li>\n<\/ul>\n<p>Now, another question arises - <strong>what\u2019s so special about the <code>MessageChannel<\/code> API?<\/strong><\/p>\n<p>It\u2019s a question I have very recently found an answer to, thanks to a very interesting <a href=\"https:\/\/www.webperf.tips\/tip\/measuring-paint-time\/#messagechannel\" target=\"_blank\" rel=\"noopener\">blog post<\/a> on <a href=\"http:\/\/webperf.tips\" target=\"_blank\" rel=\"noopener\">webperf.tips<\/a> which says that:<\/p>\n<blockquote>\n<p><code>MessageChannel<\/code>\u00a0is being used here as a generic mechanism to\u00a0<em>Post a Task to the Task Queue<\/em>.<\/p>\n<p>Furthermore, Tasks posted to the Task Queue via\u00a0<code>MessageChannel<\/code>\u00a0are\u00a0prioritized above most other Tasks.<\/p>\n<\/blockquote>\n<p>Besides rendering tasks(e.g. <strong><strong><strong>layout<\/strong><\/strong><\/strong>, <strong><strong><strong>paint, composite<\/strong><\/strong><\/strong>), there are also tasks that have to be run as a result of user interaction(e.g. <code>keyup<\/code> event) or as a result of other factors(e.g. <code>setTimeout()<\/code>, parsing a file, etc.). So, we have just learned that tasks scheduled with the help of the <code>MessageChannel<\/code> API will have higher priority compared to other non-rendering tasks. Moreover, it\u2019s important to reiterate that these <strong>non-rendering tasks<\/strong> will be <strong>executed after<\/strong> <strong>rendering tasks<\/strong>.<\/p>\n<p><a href=\"https:\/\/web.dev\/optimize-long-tasks\/#task-management-strategies\" target=\"_blank\" rel=\"noopener\">This article<\/a> describes other ways to schedule tasks, such as <strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong>yielding to the main thread<\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong>, using the <code>scheduler.postTask()<\/code>, <code>scheduler.yield()<\/code> and <code>requestIdleCallback()<\/code>, but some of these APIs are not fully supported among popular browsers or might not fulfill some requirements. It\u2019s definitely worth checking <a href=\"https:\/\/web.dev\/optimize-long-tasks\/#task-management-strategies\" target=\"_blank\" rel=\"noopener\">the article<\/a> out!<\/p>\n<h2 id=\"conclusion\">\n  <span>\n  Conclusion\n  <\/span>\n  <a href=\"#conclusion\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><p>Although this article was more about browser internals than React\u2019s <code>useEffect<\/code> hook, I believe (and hope) it was helpful in the end. Personally, I\u2019m very glad that I have got more acquainted with how browsers do their magic.<\/p>\n<p>Thanks for reading!<\/p>\n<h2 id=\"references\">\n  <span>\n  References\n  <\/span>\n  <a href=\"#references\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><p>While writing this article, I stumbled upon some very interesting resources related to how browsers work:<\/p>\n<ul>\n<li><a href=\"https:\/\/www.webperf.tips\/tip\/measuring-paint-time\/#messagechannel\" target=\"_blank\" rel=\"noopener\">https:\/\/www.webperf.tips\/tip\/measuring-paint-time<\/a><\/li>\n<li><a href=\"https:\/\/www.webperf.tips\/tip\/event-loop\/\" target=\"_blank\" rel=\"noopener\">https:\/\/www.webperf.tips\/tip\/event-loop\/<\/a><\/li>\n<li><a href=\"https:\/\/www.webperf.tips\/tip\/long-tasks\/\" target=\"_blank\" rel=\"noopener\">https:\/\/www.webperf.tips\/tip\/long-tasks\/<\/a><\/li>\n<li><a href=\"https:\/\/www.webperf.tips\/tip\/performance-timing-markers\/\" target=\"_blank\" rel=\"noopener\">https:\/\/www.webperf.tips\/tip\/performance-timing-markers\/<\/a><\/li>\n<li><a href=\"https:\/\/web.dev\/rendering-performance\/#the-pixel-pipeline\" target=\"_blank\" rel=\"noopener\">https:\/\/web.dev\/rendering-performance\/<\/a><\/li>\n<li><a href=\"https:\/\/web.dev\/optimize-long-tasks\/\" target=\"_blank\" rel=\"noopener\">https:\/\/web.dev\/optimize-long-tasks\/<\/a><\/li>\n<\/ul>\n"},{"title":"How React uses pragmas to run tests conditionally","link":"https:\/\/andreigatej.dev\/blog\/how-react-uses-pragmas-to-run-tests-conditionally\/","pubDate":"Thu, 29 Jun 2023 14:17:26 +0300","guid":"https:\/\/andreigatej.dev\/blog\/how-react-uses-pragmas-to-run-tests-conditionally\/","description":"<h2 id=\"introduction\">\n  <span>\n  Introduction\n  <\/span>\n  <a href=\"#introduction\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><p>This article is part of my learning journey as I explore React\u2019s source code. At some point, while reading some tests, I stumbled upon something like this:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-jsx\" data-lang=\"jsx\"><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ @gate enableSuspenseList\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span><span style=\"color:#a6e22e\">it<\/span>(<span style=\"color:#e6db74\">&#39;warns if an unsupported revealOrder option is used&#39;<\/span>, <span style=\"color:#66d9ef\">async<\/span> () =&gt; {\n<\/span><\/span><span style=\"display:flex;\"><span>  ....\n<\/span><\/span><span style=\"display:flex;\"><span> }); \n<\/span><\/span><\/code><\/pre><\/div><p>At first sight, it didn\u2019t tell me much - just a comment and a test case. Then, I noticed this <em>gate comment<\/em> appeared more and more frequently and then I started looking into it. In this article, I\u2019d like to share my findings, which are pretty much about Babel, Jest and a Abstract Syntax Trees.<\/p>\n<p>By the end of this article, we should get some insights regarding:<\/p>\n<ul>\n<li>the way React sets up its testing environment in a flexible way<\/li>\n<li>how Jest is smartly used by React<\/li>\n<li>what <em>pragmas<\/em> are as a general concept and how they can be implemented with Babel<\/li>\n<\/ul>\n<p>A few prerequisites for this article would be some familiarity with <a href=\"https:\/\/en.wikipedia.org\/wiki\/Abstract_syntax_tree\" target=\"_blank\" rel=\"noopener\">Abstract Syntax Trees<\/a>(henceforth AST) and some basic knowledge of <a href=\"https:\/\/babeljs.io\/\" target=\"_blank\" rel=\"noopener\">Babel<\/a>.<\/p>\n<p>Let\u2019s get the ball rolling!<\/p>\n<h2 id=\"what-are-pragmas-and-why-are-they-useful\">\n  <span>\n  What are <em>pragmas<\/em> and why are they useful?\n  <\/span>\n  <a href=\"#what-are-pragmas-and-why-are-they-useful\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><p>In simple terms, p<em>ragmas<\/em> can be thought of as additional instructions or hints given to the compiler.<\/p>\n<p>Babel is a JavaScript compiler and also provides an API whereby the developer can modify AST(i.e. Abstract Syntax Trees) nodes as they\u2019re being visited. This way, by using its API and some clever(but intuitive) logic, we can bring the concept of <em><strong>pragmas<\/strong><\/em> to Babel.<\/p>\n<p>When it comes to React, <em><strong><strong><strong>pragmas<\/strong><\/strong><\/strong><\/em> are used to run tests conditionally based on the environment. For example:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-jsx\" data-lang=\"jsx\"><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ @gate enableSuspenseList\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span><span style=\"color:#a6e22e\">it<\/span>(<span style=\"color:#e6db74\">&#39;warns if an unsupported revealOrder option is used&#39;<\/span>, <span style=\"color:#66d9ef\">async<\/span> () =&gt; {\n<\/span><\/span><span style=\"display:flex;\"><span>  ....\n<\/span><\/span><span style=\"display:flex;\"><span> }); \n<\/span><\/span><\/code><\/pre><\/div><p><em>The link to the actual test case can be found <a href=\"https:\/\/github.com\/facebook\/react\/blob\/v18.2.0\/packages\/react-reconciler\/src\/__tests__\/ReactSuspenseList-test.js#L48\" target=\"_blank\" rel=\"noopener\">here<\/a>.<\/em><\/p>\n<p>If the variable <code>enableSuspenseList<\/code>(we well see where it is defined and how exactly it is retrieved later in the article), then the test case below it will run.<\/p>\n<p>We\u2019ll see how this can be achieved in the following sections.<\/p>\n<h2 id=\"an-overview-on-reacts-testing-environment\">\n  <span>\n  An overview on React\u2019s testing environment\n  <\/span>\n  <a href=\"#an-overview-on-reacts-testing-environment\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><p>React uses Jest for testing. Since the tests cases are written using the JSX syntax, React also uses Babel to transpile the JSX code into valid JavaScript code which can then be understood by Jest.<\/p>\n<p>The way React achieves that is by using a custom Jest transformer that is to be applied for <strong>all the files<\/strong> in the code base. The Jest option that allows that is called <a href=\"https:\/\/jestjs.io\/docs\/configuration#transform-objectstring-pathtotransformer--pathtotransformer-object\" target=\"_blank\" rel=\"noopener\"><code>transform<\/code><\/a> and it can accept a function that decides how each file needed for the testing task should be processed.<\/p>\n<blockquote>\n<p>More about code transformation in Jest can be found <a href=\"https:\/\/jestjs.io\/docs\/code-transformation\" target=\"_blank\" rel=\"noopener\">here<\/a>.<\/p>\n<\/blockquote>\n<p>Concretely, React specifies the custom transformer function this way:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-jsx\" data-lang=\"jsx\"><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">transform<\/span><span style=\"color:#f92672\">:<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#e6db74\">&#39;.*&#39;<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#a6e22e\">require<\/span>.<span style=\"color:#a6e22e\">resolve<\/span>(<span style=\"color:#e6db74\">&#39;.\/preprocessor.js&#39;<\/span>),\n<\/span><\/span><span style=\"display:flex;\"><span>  }, \n<\/span><\/span><\/code><\/pre><\/div><p><em>The above snippet has been excerpted from <a href=\"https:\/\/github.com\/facebook\/react\/blob\/v18.2.0\/scripts\/jest\/config.base.js#L12-L14\" target=\"_blank\" rel=\"noopener\">this configuration file<\/a>.<\/em><\/p>\n<p>The file <code>preprocessor.js<\/code> leads to a function that, as previously mentioned, is responsible for properly processing <strong>every file<\/strong>(denoted by the <code>'.*'<\/code> regex) encountered during the testing process. Let\u2019s take a quick look at how it is defined:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-jsx\" data-lang=\"jsx\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">function<\/span>(<span style=\"color:#a6e22e\">src<\/span>, <span style=\"color:#a6e22e\">filePath<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#a6e22e\">filePath<\/span>.<span style=\"color:#a6e22e\">match<\/span>(<span style=\"color:#e6db74\">\/\\.css$\/<\/span>)) {\n<\/span><\/span><span style=\"display:flex;\"><span>\t\t<span style=\"color:#75715e\">\/\/ ...\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>  }\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#a6e22e\">filePath<\/span>.<span style=\"color:#a6e22e\">match<\/span>(<span style=\"color:#e6db74\">\/\\.coffee$\/<\/span>)) {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#75715e\">\/\/ ... Compile CoffeeScript file ...\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>  }\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#a6e22e\">filePath<\/span>.<span style=\"color:#a6e22e\">match<\/span>(<span style=\"color:#e6db74\">\/\\.ts$\/<\/span>) <span style=\"color:#f92672\">&amp;&amp;<\/span> <span style=\"color:#f92672\">!<\/span><span style=\"color:#a6e22e\">filePath<\/span>.<span style=\"color:#a6e22e\">match<\/span>(<span style=\"color:#e6db74\">\/\\.d\\.ts$\/<\/span>)) {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#75715e\">\/\/ ... Compile TypeScript file ...\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>  }\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#a6e22e\">filePath<\/span>.<span style=\"color:#a6e22e\">match<\/span>(<span style=\"color:#e6db74\">\/\\.json$\/<\/span>)) {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#75715e\">\/\/ ...\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>  }\n<\/span><\/span><span style=\"display:flex;\"><span>\t\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#75715e\">\/\/ Transpiling the source code into valid JavaScript code.\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>\t<span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#a6e22e\">babel<\/span>.<span style=\"color:#a6e22e\">transform<\/span>(\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#a6e22e\">src<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#a6e22e\">otherBabelOptions<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>\t\t)\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p><em>The link to the complete implementation can be found <a href=\"https:\/\/github.com\/facebook\/react\/blob\/v18.2.0\/scripts\/jest\/preprocessor.js#L56\" target=\"_blank\" rel=\"noopener\">here<\/a>.<\/em><\/p>\n<p>After the file has been successfully processed, it can be then loaded and executed by Jest and, as a result, the tests will finally run.<\/p>\n<p>The <strong>main takeaway<\/strong> to take from this section is that, before letting Jest do its magic, an additional preprocessing step is carried out by Babel. As we will see in the following section, during this processing step we will be able to implement a <em>pragma<\/em> that will skip a test case based on some conditions.<\/p>\n<h2 id=\"what-does-writing-a-custom-pragma-actually-involve\">\n  <span>\n  What does writing a custom pragma actually involve?\n  <\/span>\n  <a href=\"#what-does-writing-a-custom-pragma-actually-involve\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><blockquote>\n<p>As we will see, this section is heavily based on Abstract Syntax Trees(i.e AST) and their usage in Babel, so, for that, I would recommend reading a bit upon these topics from this <a href=\"https:\/\/github.com\/kentcdodds\/babel-plugin-handbook#visitors\" target=\"_blank\" rel=\"noopener\">great resource<\/a>.<\/p>\n<\/blockquote>\n<p>The short answer to the question in the title is to use a write a custom <strong>Babel plugin<\/strong> that will alter certain AST nodes such that, when Jest executes the resulted code, it will know it has to skip the test case in question.<\/p>\n<p>Let\u2019s take a simple example in order to get a better understanding of what we are trying to achieve:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-jsx\" data-lang=\"jsx\"><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ @gate shouldEnableFoo\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span><span style=\"color:#a6e22e\">fit<\/span>(<span style=\"color:#e6db74\">&#39;foo works alright&#39;<\/span>, () =&gt; {})\n<\/span><\/span><\/code><\/pre><\/div><blockquote>\n<p>There is no particular reason as to why <code>fit<\/code> has been used instead of <code>it<\/code>. <em>f<\/em> stands for <em><strong><strong>focus.<\/strong><\/strong><\/em><\/p>\n<\/blockquote>\n<p>Let\u2019s assume the variable <code>shouldEnableFoo<\/code> has been defined in a <code>.js<\/code> file and it has the value set to <code>true<\/code>. Thus, when running Jest, the test case should run.<\/p>\n<p>This is what the AST of the above snippet looks like:<\/p>\n<p><p class=\"markdown-image\">\n  <img src=\"images\/Untitled.png\" alt=\"Untitled\"  \/>\n<\/p><\/p>\n<p><em>The link to the above AST Explorer playground can be found <a href=\"https:\/\/astexplorer.net\/#\/gist\/1b109a974b9f61a5017d0efe1aa69155\/500d00eb42e3429e766be9ad52f1cf147592d3f5\" target=\"_blank\" rel=\"noopener\">here<\/a>.<\/em><\/p>\n<p>There a few things to be noticed:<\/p>\n<ul>\n<li>to AST node that encapsulates <code>fit(...)<\/code> is of type <code>ExpressionStatement<\/code><\/li>\n<li><code>ExpressionStatement<\/code> nodes can be narrowed down to even more explicit <em>expression nodes<\/em>; as can be seen in the image, <code>fit(...)<\/code> is a <code>CallExpression<\/code>(denoted by the <code>expression<\/code> property), which makes sense, because, in essence, a function is called<\/li>\n<li>another example of a more specific <code>ExpressionStatement<\/code> node is <code>BinaryExpression<\/code>:<\/li>\n<\/ul>\n<p><p class=\"markdown-image\">\n  <img src=\"images\/Untitled%201.png\" alt=\"Untitled\"  \/>\n<\/p><\/p>\n<p>Knowing the type of the AST node is central to properly creating a plugin that will allow us to implement <em><strong><strong><strong>pragmas<\/strong><\/strong><\/strong><\/em> with the help of Babel. Additional information on how to create custom Babel plugins can be found <a href=\"https:\/\/github.com\/kentcdodds\/babel-plugin-handbook#writing-your-first-babel-plugin\" target=\"_blank\" rel=\"noopener\">in this resource<\/a>, which has also been mentioned in the beginning of this section.<\/p>\n<p>Let\u2019s go a bit into detail on how this plugin will work:<\/p>\n<ul>\n<li>\n<p>it will handle AST nodes whose type is <code>ExpressionStatement<\/code> and their <code>expression<\/code> property is of type <code>CallExpression<\/code> - the reason is that each test case is defined by calling a function, e.g. <code>fit('description', () =&gt; { ... })<\/code> or <code>it('description', () =&gt; { ... })<\/code><\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-jsx\" data-lang=\"jsx\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">return<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">name<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;test-gate-pragma&#39;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">visitor<\/span><span style=\"color:#f92672\">:<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#a6e22e\">ExpressionStatement<\/span>(<span style=\"color:#a6e22e\">path<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">statement<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">path<\/span>.<span style=\"color:#a6e22e\">node<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">expression<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">statement<\/span>.<span style=\"color:#a6e22e\">expression<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#a6e22e\">expression<\/span>.<span style=\"color:#a6e22e\">type<\/span> <span style=\"color:#f92672\">===<\/span> <span style=\"color:#e6db74\">&#39;CallExpression&#39;<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>\t\t\t\t\t...\n<\/span><\/span><span style=\"display:flex;\"><span>\t\t\t}\n<\/span><\/span><span style=\"display:flex;\"><span>\t\t}\n<\/span><\/span><span style=\"display:flex;\"><span>\t}\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><\/li>\n<li>\n<p>once such AST nodes are visited, the plugin will <strong>get the comments<\/strong> that are placed right above the line where the test case is defined - since we are dealing with AST nodes, they will also contain information such as their location(e.g. line number, column number); we also have access to all of the comments in the file(along with their location as well), so we can basically filter them out based on their line number and the line number of the <code>CallExpression<\/code> node<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-jsx\" data-lang=\"jsx\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">switch<\/span> (<span style=\"color:#a6e22e\">callee<\/span>.<span style=\"color:#a6e22e\">type<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">case<\/span> <span style=\"color:#e6db74\">&#39;Identifier&#39;<\/span><span style=\"color:#f92672\">:<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">if<\/span> (\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#a6e22e\">callee<\/span>.<span style=\"color:#a6e22e\">name<\/span> <span style=\"color:#f92672\">===<\/span> <span style=\"color:#e6db74\">&#39;test&#39;<\/span> <span style=\"color:#f92672\">||<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#a6e22e\">callee<\/span>.<span style=\"color:#a6e22e\">name<\/span> <span style=\"color:#f92672\">===<\/span> <span style=\"color:#e6db74\">&#39;it&#39;<\/span> <span style=\"color:#f92672\">||<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#a6e22e\">callee<\/span>.<span style=\"color:#a6e22e\">name<\/span> <span style=\"color:#f92672\">===<\/span> <span style=\"color:#e6db74\">&#39;fit&#39;<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>    ) {\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">comments<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">statement<\/span>.<span style=\"color:#a6e22e\">leadingComments<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>\t\t\t...\n<\/span><\/span><span style=\"display:flex;\"><span>\t\t}\n<\/span><\/span><span style=\"display:flex;\"><span>\t}\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><\/li>\n<li>\n<p>if we are left with a comment that starts with <code>'@gate'<\/code>, then we can carry on and take the expression after the string<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-jsx\" data-lang=\"jsx\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">for<\/span> (<span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">line<\/span> <span style=\"color:#66d9ef\">of<\/span> <span style=\"color:#a6e22e\">comments<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">commentStr<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">line<\/span>.<span style=\"color:#a6e22e\">value<\/span>.<span style=\"color:#a6e22e\">trim<\/span>();\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#a6e22e\">commentStr<\/span>.<span style=\"color:#a6e22e\">startsWith<\/span>(<span style=\"color:#e6db74\">&#39;@gate &#39;<\/span>)) {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">code<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">commentStr<\/span>.<span style=\"color:#a6e22e\">slice<\/span>(<span style=\"color:#ae81ff\">6<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">condition<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">parse<\/span>(<span style=\"color:#a6e22e\">code<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>    ...\n<\/span><\/span><span style=\"display:flex;\"><span>  }\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><blockquote>\n<p>Some line of codes have been removed for the sake of simplicity.<\/p>\n<\/blockquote>\n<p>the <code>parse()<\/code> function will simply parse the expression, which means it will return the AST representation of that expression; this is necessary because, at this point, we are only working with ASTs<\/p>\n<\/li>\n<li>\n<p>if the expression after <code>'@gate'<\/code> is successfully parsed, then we know we have to <strong>alter this <code>CallExpression<\/code> AST node<\/strong> - the way we are going to do that is by:<\/p>\n<ul>\n<li>\n<p><strong>changing the function name<\/strong> to a name of a <strong>globally declared function<\/strong> - doing <code>expression.callee.name = 'globally_declared_function'<\/code><\/p>\n<\/li>\n<li>\n<p><code>'globally_declared_function'<\/code> will have access to an object that contains all the variables based on which tests are skipped or not and will also have access to all the initial arguments passed to <code>fit(...)<\/code>, which are the <strong>description string<\/strong> and the <strong>function that contains the assertions<\/strong><\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-jsx\" data-lang=\"jsx\"><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">callee<\/span>.<span style=\"color:#a6e22e\">name<\/span> <span style=\"color:#f92672\">=<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">callee<\/span>.<span style=\"color:#a6e22e\">name<\/span> <span style=\"color:#f92672\">===<\/span> <span style=\"color:#e6db74\">&#39;fit&#39;<\/span> <span style=\"color:#f92672\">?<\/span> <span style=\"color:#e6db74\">&#39;_test_gate_focus&#39;<\/span> <span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;_test_gate&#39;<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">expression<\/span>.<span style=\"color:#a6e22e\">arguments<\/span> <span style=\"color:#f92672\">=<\/span> [\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">t<\/span>.<span style=\"color:#a6e22e\">arrowFunctionExpression<\/span>(\n<\/span><\/span><span style=\"display:flex;\"><span>    [<span style=\"color:#a6e22e\">t<\/span>.<span style=\"color:#a6e22e\">identifier<\/span>(<span style=\"color:#e6db74\">&#39;ctx&#39;<\/span>)],\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">condition<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>  ),\n<\/span><\/span><span style=\"display:flex;\"><span>  ...<span style=\"color:#a6e22e\">expression<\/span>.<span style=\"color:#a6e22e\">arguments<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>];\n<\/span><\/span><\/code><\/pre><\/div><p>Here, <code>'globally_declared_function'<\/code> is either <code>_test_gate_focus<\/code>(when <code>fit()<\/code> has been used) or <code>_test_gate<\/code>(when <code>it()<\/code> has been used).\n<code>t.arrowFunctionExpression<\/code> will create an arrow function which implicitly returns <code>condition<\/code>.<\/p>\n<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p><em>The actual plugin implementation can be found <a href=\"https:\/\/github.com\/facebook\/react\/blob\/v18.2.0\/scripts\/babel\/transform-test-gate-pragma.js#L266-L270\" target=\"_blank\" rel=\"noopener\">here<\/a>.<\/em><\/p>\n<p>When Jest loads and executes the resulted code, it will call, in this example, <code>_test_gate_focus(gateFn, descriptionString, assertionsFunc)<\/code>, where <code>gateFn<\/code> is the <strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong>function that corresponds to the<\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong> <code>'@gate'<\/code> expression. This function will be used by <code>_test_gate_focus<\/code>, which <strong>has access<\/strong> to all the variables(which can also be thought of as flags) based on which tests will skipped or not.<\/p>\n<p>Now, the cherry on the take, the implementation of <code>_test_gate_focus<\/code>:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-jsx\" data-lang=\"jsx\"><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">global<\/span>.<span style=\"color:#a6e22e\">_test_gate_focus<\/span> <span style=\"color:#f92672\">=<\/span> (<span style=\"color:#a6e22e\">gateFn<\/span>, <span style=\"color:#a6e22e\">testName<\/span>, <span style=\"color:#a6e22e\">callback<\/span>) =&gt; {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">let<\/span> <span style=\"color:#a6e22e\">shouldPass<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">try<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">flags<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">getTestFlags<\/span>();\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#a6e22e\">shouldPass<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">gateFn<\/span>(<span style=\"color:#a6e22e\">flags<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>    } <span style=\"color:#66d9ef\">catch<\/span> (<span style=\"color:#a6e22e\">e<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#a6e22e\">test<\/span>.<span style=\"color:#a6e22e\">only<\/span>(<span style=\"color:#a6e22e\">testName<\/span>, () =&gt; {\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#66d9ef\">throw<\/span> <span style=\"color:#a6e22e\">e<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>      });\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#66d9ef\">return<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>    }\n<\/span><\/span><span style=\"display:flex;\"><span>\t\t<span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#a6e22e\">shouldPass<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#a6e22e\">test<\/span>.<span style=\"color:#a6e22e\">only<\/span>(<span style=\"color:#a6e22e\">testName<\/span>, <span style=\"color:#a6e22e\">callback<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>    } <span style=\"color:#66d9ef\">else<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#a6e22e\">test<\/span>.<span style=\"color:#a6e22e\">only<\/span>(<span style=\"color:#e6db74\">`[GATED, SHOULD FAIL] <\/span><span style=\"color:#e6db74\">${<\/span><span style=\"color:#a6e22e\">testName<\/span><span style=\"color:#e6db74\">}<\/span><span style=\"color:#e6db74\">`<\/span>, () =&gt;\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#a6e22e\">expectTestToFail<\/span>(<span style=\"color:#a6e22e\">callback<\/span>, <span style=\"color:#a6e22e\">gatedErrorMessage<\/span>));\n<\/span><\/span><span style=\"display:flex;\"><span>    }\n<\/span><\/span><span style=\"display:flex;\"><span>  }; \n<\/span><\/span><\/code><\/pre><\/div><p><em>The link for the above snippet can be found <a href=\"https:\/\/github.com\/facebook\/react\/blob\/v18.2.0\/scripts\/jest\/setupTests.js#L288\" target=\"_blank\" rel=\"noopener\">here<\/a>.<\/em><\/p>\n<ul>\n<li>\n<p><code>getTestFlags()<\/code> will get all the flags, which can come from different configuration files<\/p>\n<\/li>\n<li>\n<p>the <code>gateFn()<\/code> is invoked in order to determine whether the test should be expected to pass or not<\/p>\n<blockquote>\n<p>Until now, the notion of <em>a test being skipped<\/em> has been used, but, in reality, if the <em>gate expression<\/em> fails, the test case that corresponds to it is expected to fail as well. It is, indeed, a slight difference between a test <em>being skipped<\/em> and <em>being expected to fail<\/em> but, in my opinion, this difference is not really relevant in the context of this article.<\/p>\n<\/blockquote>\n<\/li>\n<\/ul>\n<p>To quickly recap what we have been talking about until now:<\/p>\n<ul>\n<li>React uses Jest for testing and Babel for transpiling the code from JSX to valid JavaScript code, that can then be understood by Jest<\/li>\n<li>we can implement <em>pragmas<\/em> by <strong>intervening<\/strong> in the Babel\u2019s traspiling process by creating a custom plugin<\/li>\n<li>the plugin\u2019s logic will be invoked when the <code>ExpressionStatement<\/code> nodes are visited; the logic involves, first of all, determining whether the expression is preceded by a <em>pragma comment<\/em> and then, if that\u2019s the case, wrap the test case\u2019s arguments in a globally declared function which has access to all the environment flags and which also is given a function that properly describes the <em>pragma expression<\/em>; the latter function will then be called with the environment flags<\/li>\n<li>Jest will stumble upon the globally declared function instead of the initial test case expression and that is enough to determine whether the test case should run or not<\/li>\n<\/ul>\n<p>This entire process can be visualized with the help of this diagram:<\/p>\n<p><p class=\"markdown-image\">\n  <img src=\"images\/Untitled%202.png\" alt=\"Untitled\"  \/>\n<\/p><\/p>\n<p><em>The link the to above Excalidraw diagram can be found <a href=\"https:\/\/excalidraw.com\/#json=rsX64bftFEMdh_ao0604S,djzqxSPTEcZwg__2cYb_Ng\" target=\"_blank\" rel=\"noopener\">here<\/a>.<\/em><\/p>\n<h2 id=\"conclusion\">\n  <span>\n  Conclusion\n  <\/span>\n  <a href=\"#conclusion\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><p>In this article we have gone through many concepts and, ironically, none of them directly concerned React. At least we have got a better understanding of not only how React sets up its testing environment, but also about how Babel can be used to achieve very useful features.<\/p>\n<p>Thanks for reading!<\/p>\n"},{"title":"React: how to debug the source code","link":"https:\/\/andreigatej.dev\/blog\/react-debugging-the-source-code\/","pubDate":"Mon, 12 Jun 2023 15:55:23 +0300","guid":"https:\/\/andreigatej.dev\/blog\/react-debugging-the-source-code\/","description":"<h2 id=\"introduction\">\n  <span>\n  Introduction\n  <\/span>\n  <a href=\"#introduction\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><p>I genuinely think that exploring the source code of a tool is one of the best ways to become a better programmer.<\/p>\n<p>From my experience, the more <em>magical<\/em> a tool seems, the more interesting it will be to explore its source code. Hence, in this article we&rsquo;ll see how to explore React&rsquo;s source code by debugging its tests.<\/p>\n<h2 id=\"debugging-react-in-vs-code\">\n  <span>\n  Debugging React in VS Code\n  <\/span>\n  <a href=\"#debugging-react-in-vs-code\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><p>This section will provide the necessary steps required in order to have a decent Developer Experience(i.e. DX) while debugging React&rsquo;s tests.<\/p>\n<h3 id=\"cloning-and-setting-up-the-repo\">\n  <span>\n  Cloning and setting up the repo\n  <\/span>\n  <a href=\"#cloning-and-setting-up-the-repo\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h3><div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-bash\" data-lang=\"bash\"><span style=\"display:flex;\"><span>git clone git@github.com:facebook\/react.git\n<\/span><\/span><\/code><\/pre><\/div><p>Let&rsquo;s now install the required dependencies:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-bash\" data-lang=\"bash\"><span style=\"display:flex;\"><span>cd react\n<\/span><\/span><span style=\"display:flex;\"><span>yarn\n<\/span><\/span><\/code><\/pre><\/div><h3 id=\"configure-the-launchjson-file\">\n  <span>\n  Configure the <code>launch.json<\/code> file\n  <\/span>\n  <a href=\"#configure-the-launchjson-file\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h3><p>This file is used to configure the debugger:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-json\" data-lang=\"json\"><span style=\"display:flex;\"><span>{\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#f92672\">&#34;version&#34;<\/span>: <span style=\"color:#e6db74\">&#34;0.2.0&#34;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#f92672\">&#34;configurations&#34;<\/span>: [\n<\/span><\/span><span style=\"display:flex;\"><span>    {\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#f92672\">&#34;type&#34;<\/span>: <span style=\"color:#e6db74\">&#34;node&#34;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#f92672\">&#34;request&#34;<\/span>: <span style=\"color:#e6db74\">&#34;launch&#34;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#f92672\">&#34;name&#34;<\/span>: <span style=\"color:#e6db74\">&#34;Debugging React&#39;s tests&#34;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#f92672\">&#34;runtimeExecutable&#34;<\/span>: <span style=\"color:#e6db74\">&#34;yarn&#34;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#f92672\">&#34;runtimeArgs&#34;<\/span>: [\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#e6db74\">&#34;test-classic&#34;<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>      ],\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#f92672\">&#34;sourceMaps&#34;<\/span>: <span style=\"color:#66d9ef\">true<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>    },\n<\/span><\/span><span style=\"display:flex;\"><span>  ]\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p>The <code>'test-classic'<\/code> script runs only some tests. Please refer to the <code>package.json<\/code> file to see what other types of tests can be run.<\/p>\n<p>What we&rsquo;re achieving with the configuration above is to attach the debugger to the <code>yarn test-classic<\/code> command.<\/p>\n<h3 id=\"select-a-test-file-that-youd-like-to-explore\">\n  <span>\n  Select a test file that you&rsquo;d like to explore\n  <\/span>\n  <a href=\"#select-a-test-file-that-youd-like-to-explore\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h3><p>The tests are usually located in the <code>&lt;package&gt;\/__tests__\/*<\/code> directory, where <code>&lt;package&gt;<\/code> is the package that is to be explored. For example, we can pick <code>\/react\/packages\/react-reconciler\/src\/__tests__\/ReactHooksWithNoopRenderer-test.js<\/code>, which contains many test cases for hooks.<\/p>\n<p>Once selected, please follow these steps:<\/p>\n<ol>\n<li>\n<p>get the absolute path of the file; in VS Code, this can be done by doing <code>CTRL + K P<\/code><\/p>\n<\/li>\n<li>\n<p>paste the absolute path as the value for the <code>testRegex<\/code> property from the <code>scripts\/jest\/config.base.js<\/code> file<\/p>\n<p><p class=\"markdown-image\">\n  <img src=\"images\/testRegex.png\" alt=\"testRegex\"  \/>\n<\/p><\/p>\n<\/li>\n<\/ol>\n<h3 id=\"extra-tip-for-a-better-debugging-experience\">\n  <span>\n  Extra tip for a better debugging experience\n  <\/span>\n  <a href=\"#extra-tip-for-a-better-debugging-experience\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h3><p>A test file might have a lot of test cases(denoted by the <code>it('...', () =&gt; {})<\/code> function). In order to focus on a certain test case so that Jest won&rsquo;t spend any additional time on others, you can simply change <code>it()<\/code> to <code>fit()<\/code>:<\/p>\n<p><p class=\"markdown-image\">\n  <img src=\"images\/fit.png\" alt=\"fit\"  \/>\n<\/p><\/p>\n<h3 id=\"debugging-a-test-for-the-first-time\">\n  <span>\n  Debugging a test for the first time\n  <\/span>\n  <a href=\"#debugging-a-test-for-the-first-time\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h3><p>At this step, we should have a decent set-up that should allow us to debug some tests.<\/p>\n<p>Let&rsquo;s see this in action by:<\/p>\n<ol>\n<li>\n<p>adding some breakpoints to the test file<\/p>\n<\/li>\n<li>\n<p>selecting the <em>Run and Debug<\/em> tab<\/p>\n<\/li>\n<li>\n<p>selecting the debug configuration we have set previously<\/p>\n<\/li>\n<li>\n<p>start the debugging process either by pressing on the green button or by pressing <em>F5<\/em><\/p>\n<p><p class=\"markdown-image\">\n  <img src=\"images\/selectDebug.png\" alt=\"selectDebuh\"  \/>\n<\/p><\/p>\n<\/li>\n<\/ol>\n<p>After short time(it usually takes longer than usual when run for the first time), we should see something like this:<\/p>\n<p><p class=\"markdown-image\">\n  <img src=\"images\/ugly.png\" alt=\"Ugly Code Debugging\"  \/>\n<\/p><\/p>\n<p>Although it works, it doesn&rsquo;t look very nice. Indeed, it could&rsquo;ve been worse - at least the code is not minified and\/or obfuscated. We can do better. Let&rsquo;s see how in the next section.<\/p>\n<h3 id=\"improving-the-dx---enabling-source-maps\">\n  <span>\n  Improving the DX - enabling source maps\n  <\/span>\n  <a href=\"#improving-the-dx---enabling-source-maps\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h3><p>As we have seen, the code does not look exactly like the original source code. That&rsquo;s because the source maps have not been enable.<\/p>\n<blockquote>\n<p>React uses Jest for testing and Babel to compile the JSX code that is to be used in tests.<\/p>\n<\/blockquote>\n<p>We can enable the source maps this way:<\/p>\n<ol>\n<li>\n<p>go to the <code>scripts\/jest\/preprocessor.js<\/code> file<\/p>\n<\/li>\n<li>\n<p>locate the <code>process<\/code> function<\/p>\n<\/li>\n<li>\n<p>at the end of this function, there should be an object being returned and somewhere in there should be a property called <code>sourceMaps<\/code><\/p>\n<\/li>\n<li>\n<p>set the value of <code>sourceMaps<\/code> to <code>'inline<\/code>'`<\/p>\n<p><p class=\"markdown-image\">\n  <img src=\"images\/sourceMaps.png\" alt=\"sourceMaps\"  \/>\n<\/p><\/p>\n<\/li>\n<\/ol>\n<p>Now, things look a bit nicer:<\/p>\n<p><p class=\"markdown-image\">\n  <img src=\"images\/beautiful.png\" alt=\"Beautiful Code Debugging\"  \/>\n<\/p><\/p>\n<p>There is one more problem, though. If you don&rsquo;t finish debugging in less than 5 seconds, Jest will stop the process:<\/p>\n<p><p class=\"markdown-image\">\n  <img src=\"images\/jestStop.png\" alt=\"Jest Stop Message\"  \/>\n<\/p><\/p>\n<blockquote>\n<p>Although it doesn&rsquo;t explicitly say 5 seconds, this is the <a href=\"https:\/\/jestjs.io\/docs\/configuration#testtimeout-number\" target=\"_blank\" rel=\"noopener\">default value<\/a>.<\/p>\n<\/blockquote>\n<p>Let&rsquo;s see how to solve this problem in the next section.<\/p>\n<h3 id=\"improving-the-dx---extending-the-jest-timeout\">\n  <span>\n  Improving the DX - extending the Jest timeout\n  <\/span>\n  <a href=\"#improving-the-dx---extending-the-jest-timeout\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h3><p>The solution lies in a Jest configuration property, namely <code>testTimeout<\/code>:<\/p>\n<ol>\n<li>\n<p>go to the <code>scrips\/jest\/config.base.js<\/code> file<\/p>\n<\/li>\n<li>\n<p>add the <code>testTimeout<\/code> property with a value long enough(e.g. 10 hours) so that the debugging session won&rsquo;t be interrupted when we expect the least<\/p>\n<p><p class=\"markdown-image\">\n  <img src=\"images\/testTimeout.png\" alt=\"testTimeout\"  \/>\n<\/p><\/p>\n<\/li>\n<\/ol>\n<p>Now, we should be able to debug and explore React without any inconvenience.<\/p>\n<h2 id=\"why-i-think-its-worth-it\">\n  <span>\n  Why I think it&rsquo;s worth it\n  <\/span>\n  <a href=\"#why-i-think-its-worth-it\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><p>One of my favorite aspects about exploring a tool is that I will inevitably stumble upon interesting adjacent concepts. That usually means new questions, new curiosities, new tools to be explored.<\/p>\n<p>When it comes to React(or any tool, really), I feel that knowing (mostly) what&rsquo;s going on under the hood makes me more confident in the code I write and allows me to properly investigate bugs when they appear.<\/p>\n<h2 id=\"conclusion\">\n  <span>\n  Conclusion\n  <\/span>\n  <a href=\"#conclusion\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><p>In this article, we have seen how we can set up an environment to start exploring React.<\/p>\n<p>I hope this will enrich your learning journey at least as much as it did for me.<\/p>\n<p>Thanks for reading!<\/p>\n"},{"title":"Enhancing my productivity with Vim and VS Code","link":"https:\/\/andreigatej.dev\/blog\/enhancing-my-productivity-with-vim-and-vs-code\/","pubDate":"Fri, 09 Jun 2023 19:12:10 +0300","guid":"https:\/\/andreigatej.dev\/blog\/enhancing-my-productivity-with-vim-and-vs-code\/","description":"<h2 id=\"introduction\">\n  <span>\n  Introduction\n  <\/span>\n  <a href=\"#introduction\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><p>Sincerely speaking, the beginning of my Vim journey was tough and wearying. But, as with everything that (probably) is worth pursuing, a great deal of effort is required. Fortunately, Vim was definitely worth pursuing and that\u2019s why, in this article, I\u2019d like to share some <em><strong><strong><strong><strong><strong><strong>tips &amp; tricks<\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/em> that improved my productivity while coding.<\/p>\n<h2 id=\"setting-up-vs-code-and-vim\">\n  <span>\n  Setting up VS Code and Vim\n  <\/span>\n  <a href=\"#setting-up-vs-code-and-vim\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><p>I\u2019ve been using VS Code since I started learning to code(around 2016), so it is expected that it was kind of hard for me to <em>completely<\/em> ditch VS Code. There were some commands\/shortcuts I couldn\u2019t really give up on and I was very glad to find out that VS Code and Vim really work smoothly together.<\/p>\n<p>First, you should have the VS Code\u2019s Vim extension installed.<\/p>\n<p>These are my current VS Code settings that concern Vim:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-json\" data-lang=\"json\"><span style=\"display:flex;\"><span><span style=\"color:#e6db74\">&#34;vim.handleKeys&#34;<\/span><span style=\"color:#960050;background-color:#1e0010\">:<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#f92672\">&#34;&lt;C-j&gt;&#34;<\/span>: <span style=\"color:#66d9ef\">false<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#f92672\">&#34;&lt;C-s&gt;&#34;<\/span>: <span style=\"color:#66d9ef\">false<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#f92672\">&#34;&lt;C-z&gt;&#34;<\/span>: <span style=\"color:#66d9ef\">false<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#f92672\">&#34;&lt;C-f&gt;&#34;<\/span>: <span style=\"color:#66d9ef\">false<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#f92672\">&#34;&lt;C-w&gt;&#34;<\/span>: <span style=\"color:#66d9ef\">false<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#f92672\">&#34;&lt;C-t&gt;&#34;<\/span>: <span style=\"color:#66d9ef\">false<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#f92672\">&#34;&lt;M-S-h&gt;&#34;<\/span>: <span style=\"color:#66d9ef\">false<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#f92672\">&#34;&lt;C-n&gt;&#34;<\/span>: <span style=\"color:#66d9ef\">false<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#f92672\">&#34;&lt;C-S-4&gt;&#34;<\/span>: <span style=\"color:#66d9ef\">false<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#f92672\">&#34;&lt;C-S-3&gt;&#34;<\/span>: <span style=\"color:#66d9ef\">false<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>    }<span style=\"color:#960050;background-color:#1e0010\">,<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#e6db74\">&#34;editor.lineNumbers&#34;<\/span><span style=\"color:#960050;background-color:#1e0010\">:<\/span> <span style=\"color:#e6db74\">&#34;relative&#34;<\/span><span style=\"color:#960050;background-color:#1e0010\">,<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#e6db74\">&#34;vim.vimrc.path&#34;<\/span><span style=\"color:#960050;background-color:#1e0010\">:<\/span> <span style=\"color:#e6db74\">&#34;~\/.vimrc&#34;<\/span><span style=\"color:#960050;background-color:#1e0010\">,<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#e6db74\">&#34;vim.vimrc.enable&#34;<\/span><span style=\"color:#960050;background-color:#1e0010\">:<\/span> <span style=\"color:#66d9ef\">true<\/span><span style=\"color:#960050;background-color:#1e0010\">,<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#e6db74\">&#34;vim.normalModeKeyBindingsNonRecursive&#34;<\/span><span style=\"color:#960050;background-color:#1e0010\">:<\/span> [\n<\/span><\/span><span style=\"display:flex;\"><span>        {\n<\/span><\/span><span style=\"display:flex;\"><span>            <span style=\"color:#f92672\">&#34;before&#34;<\/span>: [\n<\/span><\/span><span style=\"display:flex;\"><span>                <span style=\"color:#e6db74\">&#34;u&#34;<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>            ],\n<\/span><\/span><span style=\"display:flex;\"><span>            <span style=\"color:#f92672\">&#34;after&#34;<\/span>: [],\n<\/span><\/span><span style=\"display:flex;\"><span>            <span style=\"color:#f92672\">&#34;commands&#34;<\/span>: [\n<\/span><\/span><span style=\"display:flex;\"><span>                {\n<\/span><\/span><span style=\"display:flex;\"><span>                    <span style=\"color:#f92672\">&#34;command&#34;<\/span>: <span style=\"color:#e6db74\">&#34;undo&#34;<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>                }\n<\/span><\/span><span style=\"display:flex;\"><span>            ]\n<\/span><\/span><span style=\"display:flex;\"><span>        },\n<\/span><\/span><span style=\"display:flex;\"><span>        {\n<\/span><\/span><span style=\"display:flex;\"><span>            <span style=\"color:#f92672\">&#34;before&#34;<\/span>: [\n<\/span><\/span><span style=\"display:flex;\"><span>                <span style=\"color:#e6db74\">&#34;&lt;C-r&gt;&#34;<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>            ],\n<\/span><\/span><span style=\"display:flex;\"><span>            <span style=\"color:#f92672\">&#34;after&#34;<\/span>: [],\n<\/span><\/span><span style=\"display:flex;\"><span>            <span style=\"color:#f92672\">&#34;commands&#34;<\/span>: [\n<\/span><\/span><span style=\"display:flex;\"><span>                {\n<\/span><\/span><span style=\"display:flex;\"><span>                    <span style=\"color:#f92672\">&#34;command&#34;<\/span>: <span style=\"color:#e6db74\">&#34;redo&#34;<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>                }\n<\/span><\/span><span style=\"display:flex;\"><span>            ]\n<\/span><\/span><span style=\"display:flex;\"><span>        }\n<\/span><\/span><span style=\"display:flex;\"><span>    ]<span style=\"color:#960050;background-color:#1e0010\">,<\/span>\n<\/span><\/span><\/code><\/pre><\/div><ul>\n<li><code>&quot;vim.handleKeys&quot;<\/code>: specifies which key combinations should be handled by VS Code instead of Vim<\/li>\n<li><code>&quot;vim.vimrc.*&quot;<\/code>: makes possible importing the settings from the <code>.vimrc<\/code> file as well<\/li>\n<\/ul>\n<p>And this is what the <code>.vimrc<\/code> file looks like:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-json\" data-lang=\"json\"><span style=\"display:flex;\"><span><span style=\"color:#960050;background-color:#1e0010\">:set<\/span> <span style=\"color:#960050;background-color:#1e0010\">number<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#960050;background-color:#1e0010\">:set<\/span> <span style=\"color:#960050;background-color:#1e0010\">relativenumber<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#960050;background-color:#1e0010\">:set<\/span> <span style=\"color:#960050;background-color:#1e0010\">rnu<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#960050;background-color:#1e0010\">runtime<\/span> <span style=\"color:#960050;background-color:#1e0010\">macros\/matchit.vim<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#960050;background-color:#1e0010\">filetype<\/span> <span style=\"color:#960050;background-color:#1e0010\">plugin<\/span> <span style=\"color:#960050;background-color:#1e0010\">on<\/span>\n<\/span><\/span><\/code><\/pre><\/div><h2 id=\"improving-my-workflows\">\n  <span>\n  Improving my workflows\n  <\/span>\n  <a href=\"#improving-my-workflows\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><h3 id=\"enabling-relative-line-numbers\">\n  <span>\n  Enabling relative line numbers\n  <\/span>\n  <a href=\"#enabling-relative-line-numbers\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h3><p>Arguably, this is among my favorites.<\/p>\n<p>To quickly demonstrate this feature\u2019s usefulness, consider this scenario, where you are on line 34 and want to quickly get to line 60 and edit the <code>&lt;a&gt;<\/code>&rsquo;s href:<\/p>\n<p><p class=\"markdown-image\">\n  <img src=\"images\/Untitled.png\" alt=\"Untitled\"  \/>\n<\/p><\/p>\n<p>There may be many ways to achieve this(e.g. doing the math, doing <code>26J<\/code> and then edit, going directly to line 60 and edit, using your mouse, etc.,), but, from my experience, the fastest way to do that is to enable relative line numbers(e.g. the <code>&quot;editor.lineNumbers&quot;: &quot;relative&quot;<\/code> setting in VS Code)<\/p>\n<p><p class=\"markdown-image\">\n  <img src=\"images\/Untitled%201.png\" alt=\"Untitled\"  \/>\n<\/p><\/p>\n<p>and then perform:<\/p>\n<ul>\n<li><code>26J<\/code> - notice you don\u2019t need to do the math yourself!<\/li>\n<li><code>f=;w<\/code> - move the cursor to the first character of the <code>href<\/code>&rsquo;s value<\/li>\n<li><code>ci&quot;<\/code> - start editing<\/li>\n<\/ul>\n<p>Relative numbers can provide huge speed improvements when it comes to navigating through a file, so it\u2019s something I could hardly work without.<\/p>\n<h3 id=\"selecting-paragraphs\">\n  <span>\n  Selecting paragraphs\n  <\/span>\n  <a href=\"#selecting-paragraphs\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h3><p>The text objects that correspond to paragraphs are <code>{<\/code>(for moving backward) and <code>}<\/code>(for moving forward). There is also <code>p<\/code>, but it would be exemplified later in this article.<\/p>\n<p>Selecting paragraphs becomes very helpful when writing SQL queries directly in VS Code, as I did for some of my projects.<\/p>\n<p>Let\u2019s say that we want to run this query(and we want to do that very quickly, of course):<\/p>\n<p><p class=\"markdown-image\">\n  <img src=\"images\/Untitled%202.png\" alt=\"Untitled\"  \/>\n<\/p><\/p>\n<p>Notice that the cursor is in the middle of the query. What we really want now is to be able to select the entire query and press a button to run it.<\/p>\n<blockquote>\n<p>Although the query seems to be already selected, there have been cases where directly trying to run it didn\u2019t work. Regardless of that, I think this is a feature of Vim worth knowing.<\/p>\n<\/blockquote>\n<p>This is the fastest way I could select the entire query and run it:<\/p>\n<ul>\n<li><code>{<\/code> - go backward one paragraph, e.g. on line 10 on the top<\/li>\n<li><code>V<\/code> - select the entire line<\/li>\n<li><code>}<\/code> go forward one paragraph, e.g. on line 10 in the bottom<\/li>\n<li>run the query<\/li>\n<\/ul>\n<h3 id=\"automatically-increment-numbers\">\n  <span>\n  Automatically increment numbers\n  <\/span>\n  <a href=\"#automatically-increment-numbers\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h3><p>This example might seem a bit contrived, but it\u2019s definitely useful when creating placeholder or seeding data.<\/p>\n<p>Let\u2019s say that we want to create a placeholder array with <em>N<\/em> entities, starting from this:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-jsx\" data-lang=\"jsx\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">return<\/span> [\n<\/span><\/span><span style=\"display:flex;\"><span>  { <span style=\"color:#a6e22e\">id<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#ae81ff\">1<\/span>, <span style=\"color:#a6e22e\">subjectName<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;Subject1&#39;<\/span>, <span style=\"color:#a6e22e\">studentsCount<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#ae81ff\">10<\/span> },\n<\/span><\/span><span style=\"display:flex;\"><span>]\n<\/span><\/span><\/code><\/pre><\/div><p>Instead of copying the line, pasting it <em>N<\/em> times and then manually increment the values, I prefer following these steps:<\/p>\n<ul>\n<li><code>Y<\/code> - copy the first placeholder entity<\/li>\n<li><code>5p<\/code> - paste what\u2019s been copied 5 times<\/li>\n<li>go to the <code>id<\/code> value of the second entity<\/li>\n<li><code>CTRL+v<\/code> - enter the column-oriented visual mode<\/li>\n<li><code>4j<\/code> - select until the last column<\/li>\n<li><code>gCTRL+a<\/code> - automatically increment the selected numbers<\/li>\n<\/ul>\n<p>Here\u2019s a GIF that illustrates the above steps:<\/p>\n<p><p class=\"markdown-image\">\n  <img src=\"images\/7ospra.gif\" alt=\"7ospra.gif\"  \/>\n<\/p><\/p>\n<h3 id=\"editing-paragraphs-that-contain-curly-braces\">\n  <span>\n  Editing paragraphs that contain curly braces\n  <\/span>\n  <a href=\"#editing-paragraphs-that-contain-curly-braces\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h3><p>Consider this CSS snippet:<\/p>\n<p><p class=\"markdown-image\">\n  <img src=\"images\/Untitled%203.png\" alt=\"Untitled\"  \/>\n<\/p><\/p>\n<p>Let\u2019s suppose we\u2019d like to completely override the <code>section.class-header<\/code> paragraph. One may be tempted to go to line 4 and press <code>ca}<\/code>, but that will only lead to this:<\/p>\n<p><p class=\"markdown-image\">\n  <img src=\"images\/Untitled%204.png\" alt=\"Untitled\"  \/>\n<\/p><\/p>\n<p>The reason is that <code>ca}<\/code> is translated to **************<em>change around <code>}<\/code> and its pair, which is <code>{<\/code>.<\/em> Luckily, there is another way to refer to paragraph text objects in Vim - via <code>p<\/code>.<\/p>\n<p>So, in order to achieve that we initially wanted, we can:<\/p>\n<ul>\n<li>go to the line where the paragraph starts(i.e. the line with <code>section.class-header<\/code>)<\/li>\n<li><code>cap<\/code> - change around paragraph<\/li>\n<\/ul>\n<p>Here\u2019s a GIF with the above steps:<\/p>\n<p><p class=\"markdown-image\">\n  <img src=\"images\/7oss4a.gif\" alt=\"7oss4a.gif\"  \/>\n<\/p><\/p>\n<h3 id=\"toggle-between-the-beginning-and-the-end-of-a-selection\">\n  <span>\n  Toggle between the beginning and the end of a selection\n  <\/span>\n  <a href=\"#toggle-between-the-beginning-and-the-end-of-a-selection\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h3><p>A concrete situation would be this: we have already started selecting downwards, but we suddenly realize that we need to also select a piece of what\u2019s above the line we initially started selecting from. In other words, we might need so select downwards, then upwards.<\/p>\n<p>We can toggle between the beginning and the end of a selection by typing <code>O<\/code>.<\/p>\n<p>Here\u2019s an example of that:<\/p>\n<p><p class=\"markdown-image\">\n  <img src=\"images\/7ostcs.gif\" alt=\"7ostcs.gif\"  \/>\n<\/p><\/p>\n<h3 id=\"quickly-deleting-an-unused-import\">\n  <span>\n  Quickly deleting an unused import\n  <\/span>\n  <a href=\"#quickly-deleting-an-unused-import\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h3><p>We\u2019re given this situation, where we want to delete <code>BadGatewayException<\/code>, because it\u2019s not used at all in this file:<\/p>\n<p><p class=\"markdown-image\">\n  <img src=\"images\/Untitled%205.png\" alt=\"Untitled\"  \/>\n<\/p><\/p>\n<p>We are all familiar with how one could delete a word - <code>diw<\/code>. However, by doing that, we are left with a dangling comma:<\/p>\n<p><p class=\"markdown-image\">\n  <img src=\"images\/Untitled%206.png\" alt=\"Untitled\"  \/>\n<\/p><\/p>\n<p>Of course, that could easily be deleted by typing <code>xx<\/code>.<\/p>\n<p>My preferred way to achieve the same result with a single combination of keystrokes is <code>daW<\/code> - <strong><strong><strong><strong><strong><strong><strong><strong><strong>delete around word<\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong>, and <code>W<\/code> has been used instead of <code>w<\/code> because <code>W<\/code> will not consider punctuation symbols(e.g. <code>,<\/code>, <code>;<\/code>, etc.) as separate words. To put it another way, <code>W<\/code> considers that words are only separated by spaces.<\/p>\n<p>Here is what we end up with after putting the cursor on the thing we want to remove and pressing <code>daW<\/code>:<\/p>\n<p><p class=\"markdown-image\">\n  <img src=\"images\/Untitled%207.png\" alt=\"Untitled\"  \/>\n<\/p><\/p>\n<h3 id=\"changing-inside-quotes-regardless-of-where-the-cursor-is-on-the-line\">\n  <span>\n  Changing inside quotes regardless of where the cursor is on the line\n  <\/span>\n  <a href=\"#changing-inside-quotes-regardless-of-where-the-cursor-is-on-the-line\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h3><p>Let\u2019s say we want to quickly update the styles import:<\/p>\n<p><p class=\"markdown-image\">\n  <img src=\"images\/Untitled%208.png\" alt=\"Untitled\"  \/>\n<\/p><\/p>\n<p>One way to do that would be to, first of all, go to the line below(i.e. <code>j<\/code>), then <code>f'<\/code> to move the cursor to the first quote, then <code>w<\/code> to move inside the quotes and, finally, <code>ci'<\/code> to edit the value inside the quotes.<\/p>\n<p>I was very happy to find out that the four steps described above and be narrowed down to only two:<\/p>\n<ul>\n<li><code>j<\/code> - move to the line below<\/li>\n<li><code>ci\u2019<\/code> - edit the contents inside the single quotes<\/li>\n<\/ul>\n<p>Note that <strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong>it may not work as expected<\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong> if there are multiple pairs of quotes on the same line.<\/p>\n<h2 id=\"why-i-think-vim-is-worth-it\">\n  <span>\n  Why I think Vim is worth it\n  <\/span>\n  <a href=\"#why-i-think-vim-is-worth-it\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><p>At the time of writing this article(June 2023), I could say that I\u2019ve been on this <em><strong><strong><strong><strong><strong>Vim journey<\/strong><\/strong><\/strong><\/strong><\/strong><\/em> for almost 6 moths.<\/p>\n<p>One thing that I\u2019ve noticed recently, which is also the reason as to why I\u2019m writing this article, is that being <strong><strong>in the flow<\/strong><\/strong> is much more pleasant since I\u2019m no longer <strong><strong>wasting extra time<\/strong><\/strong> on performing an action and I can move more rapidly to the next idea instead. What I\u2019d define <strong><strong><strong><strong><strong>extra time<\/strong><\/strong><\/strong><\/strong><\/strong> like is moving to line X using <code>CTRL + arrows<\/code> or mouse, then use <code>CTRL + arrows<\/code> to move to the word I want modify, then go back,* etc. Such actions usually took place after I had made a decision on a given problem and, at a certain point, it became annoying to keep the same <em><strong><strong><strong><strong><strong><strong><strong><strong><strong>solved problem<\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/strong><\/em> in my mind while performing the steps to actually get it to completion. What Vim really allowed me to do is to spend as least time as possible on performing such actions and to move onto the next problem that is to be solved much faster.<\/p>\n<h2 id=\"future-plans\">\n  <span>\n  Future plans\n  <\/span>\n  <a href=\"#future-plans\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><p>When it comes to Vim, there is still a lot of learn and, more importantly, to improve. Besides reading materials on Vim and trying things out myself, I plan to give Neovim a try.<\/p>\n<h2 id=\"aknowledgements\">\n  <span>\n  Aknowledgements\n  <\/span>\n  <a href=\"#aknowledgements\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><p>I would say that this journey wouldn\u2019t have been possible if a good friend of mine, <a href=\"https:\/\/twitter.com\/ovstoica\" target=\"_blank\" rel=\"noopener\">Ovi Stoica<\/a>, hadn\u2019t recommended to try out Vim.<\/p>\n<p>Lastly, seeing how fast <a href=\"https:\/\/www.youtube.com\/@ThePrimeagen\/videos\" target=\"_blank\" rel=\"noopener\">ThePrimeagen<\/a> codes, I felt greatly inspired.<\/p>\n<h2 id=\"conclusion\">\n  <span>\n  Conclusion\n  <\/span>\n  <a href=\"#conclusion\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><p>I\u2019m sure that there are many handy features that have yet to be discovered. I will update this article as I find new interesting stuff worth sharing.<\/p>\n<p>If you plan to learn Vim, regardless of how frustrating it may seem in the beginning, it\u2019s worth giving a try(or more tries, as I did myself).<\/p>\n<p>Thanks for reading!<\/p>\n"},{"title":"Exploring how virtual DOM is implemented in React","link":"https:\/\/andreigatej.dev\/blog\/exploring-how-virtual-dom-is-implemented-in-react\/","pubDate":"Tue, 03 May 2022 00:00:00 +0000","guid":"https:\/\/andreigatej.dev\/blog\/exploring-how-virtual-dom-is-implemented-in-react\/","description":"<p><em>This article has been published on <a href=\"https:\/\/indepth.dev\/posts\/1501\/exploring-how-virtual-dom-is-implemented-in-react\" target=\"_blank\" rel=\"noopener\">indepth.dev<\/a>.<\/em><\/p>\n<h2 id=\"introduction\">\n  <span>\n  Introduction\n  <\/span>\n  <a href=\"#introduction\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><p>It is almost inevitable to stumble across the term <em>virtual DOM<\/em> in your React learning journey(which I doubt it will ever end). This article aims to clarify how the <em>virtual DOM<\/em> is actually implemented in React and set the stage for future writings that will expand on different <em>virtual DOM<\/em> features and behaviours, such as: deleting elements, updating state and props, working with lists and more.<\/p>\n<p>Before we get the ball rolling, I\u2019d kindly suggest to ponder this question a bit: <em>How do you think the virtual DOM is implemented in React?<\/em> You might have already read a pile of materials that cover this topic, therefore thinking about the actual implementation based on the knowledge acquired so far might help you get the most out of this article.<\/p>\n<p>Some prerequisites would be some familiarity with React and a decent understanding of JavaScript. Let\u2019s get started!<\/p>\n<h2 id=\"about-the-virtual-dom\">\n  <span>\n  About the virtual DOM\n  <\/span>\n  <a href=\"#about-the-virtual-dom\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><p>As we know, the DOM is a tree-like structure that is used to represent a web page. It provides an interface through which developers can perform certain operations on that page, such as fetching information and altering the content\/structure. However, operating <strong>directly<\/strong> on the DOM is something that shouldn\u2019t be done more often than actually required because it is a <strong>slow process<\/strong>. Even <a href=\"https:\/\/gist.github.com\/paulirish\/5d52fb081b3570c81e3a\" target=\"_blank\" rel=\"noopener\">accessing some element\u2019s properties<\/a>, such as <code>offsetHeight<\/code>, would result in a browser reflow, which is <strong>can be computationally expensive<\/strong>.<\/p>\n<p>So, operations on the DOM should be done when needed and efficiently. <strong>This is where the <em>virtual DOM<\/em> comes into play.<\/strong> The <em>virtual DOM<\/em> is also tree-like structure, kept in memory, that stores the elements of a page, but it comes with the benefit that performing any work on is cheaper and faster, compared to its counterpart. It is the <em>virtual DOM<\/em> that takes on the responsibility of determining what has changed in terms of content\/structure and then all the modifications are committed on the <strong>actual DOM<\/strong> at once.<\/p>\n<p>At its core, the <em>virtual DOM<\/em> is just a <strong>tree of so-called <code>FiberNode<\/code>s<\/strong>(we will refer to it as <code>FiberTree<\/code>). As we will see, these nodes are just <strong>JavaScript objects<\/strong> with some properties that are very cleverly leveraged.<\/p>\n<p>In the next section, as another small introductory step, we will see what a <code>FiberNode<\/code> is about.<\/p>\n<h2 id=\"becoming-familiar-with-what-a-fibernode-is\">\n  <span>\n  Becoming familiar with what a FiberNode is\n  <\/span>\n  <a href=\"#becoming-familiar-with-what-a-fibernode-is\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><p>Since the <code>FiberTree<\/code> is built from the compiled JSX, we could say that there is a <code>FiberNode<\/code> for each <a href=\"https:\/\/reactjs.org\/blog\/2015\/12\/18\/react-components-elements-and-instances.html#elements-describe-the-tree\" target=\"_blank\" rel=\"noopener\">React element<\/a>. Although this is not always true(e.g. certain elements can lead to more <code>FiberNodes<\/code> being created), we will stick to this principle for now because it won\u2019t impede our understanding process.<\/p>\n<p>So, from the following JSX snippet:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-tsx\" data-lang=\"tsx\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">function<\/span> <span style=\"color:#a6e22e\">App<\/span> () {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">return<\/span> (\n<\/span><\/span><span style=\"display:flex;\"><span>    &lt;<span style=\"color:#f92672\">article<\/span>&gt;\n<\/span><\/span><span style=\"display:flex;\"><span>      &lt;<span style=\"color:#f92672\">h2<\/span>&gt;<span style=\"color:#a6e22e\">Title<\/span>&lt;\/<span style=\"color:#f92672\">h2<\/span>&gt;\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>      &lt;<span style=\"color:#f92672\">p<\/span>&gt;<span style=\"color:#a6e22e\">Some<\/span> <span style=\"color:#a6e22e\">content<\/span>&lt;\/<span style=\"color:#f92672\">p<\/span>&gt;\n<\/span><\/span><span style=\"display:flex;\"><span>    &lt;\/<span style=\"color:#f92672\">article<\/span>&gt;\n<\/span><\/span><span style=\"display:flex;\"><span>  )\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p>we\u2019d end up with 4 <code>FiberNode<\/code>s, one for each of the following: the <code>App<\/code> function component, the <code>&lt;article&gt;<\/code> tag, the <code>&lt;h2&gt;<\/code> tag and the <code>&lt;p&gt;<\/code> tag. There is also a <strong>root<\/strong> <code>FiberNode<\/code>, but it is not relevant now.<\/p>\n<p>The relationships between the React elements persist when it comes to <code>FiberNode<\/code>s. For instance, we could intuitively say that the <code>App<\/code>&rsquo;s <code>FiberNode<\/code> will be the parent of the <code>&lt;article&gt;<\/code>&rsquo;s <code>FiberNode<\/code>. As far as the <code>&lt;h2&gt;<\/code> and <code>&lt;p&gt;<\/code> blog_tags are concerned, there is no parent-child relationship, but a <strong>sibling relationship<\/strong>.<\/p>\n<p>In the above paragraph we\u2019ve already listed some of the most important <code>FiberNode<\/code>&rsquo;s properties:<\/p>\n<ul>\n<li><code>child<\/code>: <code>AppFiberNode.child === ArticleFiberNode<\/code><\/li>\n<li><code>sibling<\/code>: \u00a0<code>H2FiberNode.sibling === PFiberNode<\/code><\/li>\n<li><code>return<\/code>: arguably, this might be the least intuitive, but it can be thought of as the <strong>parent<\/strong> <code>FiberNode<\/code> - <code>H2FiberNode.return === ArticleFiberNode<\/code> and also <code>PFiberNode.return === ArticleFiberNode<\/code>(so, all the siblings have a reference to their parent <code>FiberNode<\/code>); an explanation as to why it is called <code>return<\/code> instead of <code>parent<\/code> can be found in <a href=\"https:\/\/github.com\/acdlite\/react-fiber-architecture#return\" target=\"_blank\" rel=\"noopener\">this document<\/a> written by <a href=\"https:\/\/github.com\/acdlite\" target=\"_blank\" rel=\"noopener\">Andrew Clark<\/a>; for the rest of the article, we will use <code>return<\/code> and <code>parent<\/code> interchangeably<\/li>\n<\/ul>\n<p>This would be a plain visualization of the above <code>FiberTree<\/code>:<\/p>\n<p><p class=\"markdown-image\">\n  <img src=\"images\/simple-fiber-tree-2.png\" alt=\"Content image\"  \/>\n<\/p><\/p>\n<p><em>The link for the above diagram can be found <a href=\"https:\/\/excalidraw.com\/#json=1FroN8EyyXg-r0g7OzdOO,gFKVP94j1Wvl4vtRhqkd4A\" target=\"_blank\" rel=\"noopener\">here<\/a>.<\/em><\/p>\n<p>However, recall that the <em>virtual DOM<\/em> is responsible for <strong>determining what\u2019s changed<\/strong> and also for <strong>collecting the changes<\/strong> so that they can be <strong>committed all at once<\/strong> so that the browser can render the new content. For now, all we have is a way to organize the React elements based on the relationships between them. But we need more than that, we also need a way to tell whether changes(of any kind) have occurred or not within a <code>FiberNode<\/code>. Therefore, we will have to <strong>introduce another powerful property<\/strong> of the <code>FiberNode<\/code>, which is vital for the <strong><a href=\"https:\/\/reactjs.org\/blog\/2018\/09\/10\/introducing-the-react-profiler.html#browsing-commits\" target=\"_blank\" rel=\"noopener\">render phase<\/a><\/strong>: <code>alternate<\/code>.<\/p>\n<p>Firstly, let\u2019s state once again the problem that is to be solved: <em>how to determine the changes that have been made in a <code>FiberNode<\/code>?<\/em> Suppose there is a React element that displays a counter\u2019s value:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-tsx\" data-lang=\"tsx\"><span style=\"display:flex;\"><span>&lt;<span style=\"color:#f92672\">p<\/span>&gt;{<span style=\"color:#a6e22e\">counter<\/span>}&lt;\/<span style=\"color:#f92672\">p<\/span>&gt;\n<\/span><\/span><\/code><\/pre><\/div><p>we need to find a way to not miss any updates on the <code>counter<\/code> value. Keep in mind that, in order to find any modifications, we will have to <strong>traverse the <code>FiberTree<\/code><\/strong>. Imagine the <code>FiberNode<\/code> of the above element is now being visited, how would one be able to tell that something has changed?<\/p>\n<p>We need <strong>something to compare against<\/strong> and this is where the <code>alternate<\/code> property plays an important role. In this case, where we want to discover any updates, <code>alternate<\/code> will refer to the previous state of a <code>FiberNode<\/code>. Yes, an <code>alternate<\/code> property of a <code>FiberNode<\/code> will also point to a <code>FiberNode<\/code>! It\u2019s like having <strong>2 copies<\/strong> of the same <code>FiberNode<\/code>, one which stores the value that is, <strong>at this moment<\/strong>, <strong>visible in the browser,<\/strong> while the other stores the <strong>new changes<\/strong> that <strong>have to be reflected in the browser<\/strong>. So, we can determine whether there is something to commit later on if the <em>state<\/em> of the <strong>previous<\/strong> <code>FiberNode<\/code> differs from the state of the <strong>newly updated<\/strong> <code>FiberNode<\/code>.<\/p>\n<p>There is a <em>formal<\/em> way to define the <code>alternate<\/code> property\u2019s usefulness and we will do this in the next section, by going into detail about the two possible states of a <code>FiberNode<\/code>: <code>current<\/code>(the state that <strong>is now reflected in the browser<\/strong>) and <code>workInProgress<\/code>(the state that <strong>is to be reflected in the browser<\/strong>).<\/p>\n<h2 id=\"the-current-and-workinprogress-states-of-a-fibernode\">\n  <span>\n  The current and workInProgress states of a FiberNode\n  <\/span>\n  <a href=\"#the-current-and-workinprogress-states-of-a-fibernode\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><p>Let\u2019s restate the <strong>purpose<\/strong> of these 2 <em>states<\/em> of a single <code>FiberNode<\/code>: we need to <strong>find and collect<\/strong> all the <strong>changes<\/strong> that have occurred in the tree so that all the necessary updates will be incurred by the real DOM at once\/in a single batch. The way to find a change in the <code>FiberTree<\/code> is by <strong>comparing<\/strong> what\u2019s currently being shown on the screen(i.e. the <code>current<\/code> <code>FiberNode<\/code>) with what will be shown on the screen(i.e. the <code>workInProgress<\/code> <code>FiberNode<\/code>).<\/p>\n<p>In the diagrams that will follow we will include both the <code>current<\/code> and the <code>workInProgress<\/code> <code>FiberNodes<\/code> for a single React element. For instance, this is how an <code>&lt;article&gt;<\/code> tag will be illustrated:<\/p>\n<p><p class=\"markdown-image\">\n  <img src=\"images\/single-fiber-node-in-tree.png\" alt=\"Content image\"  \/>\n<\/p><\/p>\n<p>In the image above, there are 2 <code>FiberNode<\/code>s that correspond to an <code>article<\/code> element: <code>current<\/code> and <code>workInProgress<\/code>(abbreviated as <em>WIP<\/em>). One can access its counterpart via the <code>alternate<\/code> property:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ `workInProgress === current.alternate` \/\/ true\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ `workInProgress.alternate === current` \/\/ true\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span><span style=\"color:#a6e22e\">current<\/span> <span style=\"color:#f92672\">===<\/span> <span style=\"color:#a6e22e\">current<\/span>.<span style=\"color:#a6e22e\">alternate<\/span>.<span style=\"color:#a6e22e\">alternate<\/span> <span style=\"color:#75715e\">\/\/ true\n<\/span><\/span><\/span><\/code><\/pre><\/div><p>Before moving on, let\u2019s find a possible answer to another interesting question: <em>why is this property called <code>alternate<\/code>?<\/em> My take on this is that these 2 <code>FiberNode<\/code>s, <code>current<\/code> and <code>workInProgress<\/code>, continuously <em>alternate<\/em> across browser renderings. Suppose there is a <code>Counter<\/code> component rendered in the browser with the value <code>10<\/code>. If the <code>Increment<\/code> button is clicked, then the 2 <code>FiberNode<\/code>s associated with the <code>Counter<\/code> component will look like this:<\/p>\n<ul>\n<li><code>current<\/code> - has the value of <code>10<\/code>, because it is what\u2019s currently being shown in the browser<\/li>\n<li><code>workInProgress<\/code> - has the value of <code>11<\/code>, because it contains the change that has to be performed<\/li>\n<\/ul>\n<p>After <strong>comparing<\/strong> <code>current<\/code>&rsquo;s state with <code>workInProgress<\/code>&rsquo; state, a modification has been discovered(going from <code>10<\/code> to <code>11<\/code>) and it will eventually be <strong>reflected in the browser<\/strong>. <strong>After this happens<\/strong>, it is expected for the <strong>barely resolved<\/strong> <code>workInProgress<\/code> to <strong>become<\/strong> <code>current<\/code>. That\u2019s because if the user clicks on the <code>Increment<\/code> button once again, then the same logic will be applied and <code>current<\/code> will have the value of <code>11<\/code>(the value of the <strong>old<\/strong> <code>workInProgress<\/code>), whereas the <strong>new<\/strong> value of <code>workInProgress<\/code> will be <code>12<\/code>. As you can probably anticipate, the alternation goes on and on: when some work has to be done on the <code>FiberTree<\/code>, <code>current<\/code> reflects the current state visible in the browser, then, after the changes have been applied to the DOM, \u00a0<code>workInProgress<\/code> becomes <code>current<\/code>.<\/p>\n<p>The next section is meant to clarify these concepts even further with the help of some diagrams.<\/p>\n<h2 id=\"a-hands-on-example-to-grasp-the-fibertree\">\n  <span>\n  A hands-on example to grasp the FiberTree\n  <\/span>\n  <a href=\"#a-hands-on-example-to-grasp-the-fibertree\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><p><em>All the diagrams used in this section can be found in this <a href=\"https:\/\/excalidraw.com\/#json=sVh5iAmG_QQrJGZI91STQ,MA7J2M1WJf-CTRenCvTINg\" target=\"_blank\" rel=\"noopener\">Excalidraw workspace<\/a>.<\/em><\/p>\n<p>This section aims at illustrating how the <em>virtual DOM<\/em>(and thus the <code>FiberTree<\/code>) works, with the help of a simple application and some comprehensive diagrams.<\/p>\n<p><a href=\"https:\/\/stackblitz.com\/edit\/react-ts-ye87vy?file=index.tsx\" target=\"_blank\" rel=\"noopener\">This the demo application<\/a> that we will follow:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ index.tsx\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span><span style=\"color:#66d9ef\">function<\/span> <span style=\"color:#a6e22e\">App() {<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">return<\/span> (\n<\/span><\/span><span style=\"display:flex;\"><span>    &lt;<span style=\"color:#f92672\">div<\/span>&gt;\n<\/span><\/span><span style=\"display:flex;\"><span>      &lt;<span style=\"color:#f92672\">h2<\/span>&gt;&lt;<span style=\"color:#f92672\">i<\/span>&gt;<span style=\"color:#a6e22e\">Welcome<\/span> <span style=\"color:#a6e22e\">world<\/span><span style=\"color:#f92672\">!<\/span>&lt;\/<span style=\"color:#f92672\">i<\/span>&gt;&lt;\/<span style=\"color:#f92672\">h2<\/span>&gt;\n<\/span><\/span><span style=\"display:flex;\"><span>      \n<\/span><\/span><span style=\"display:flex;\"><span>      &lt;<span style=\"color:#f92672\">Counter<\/span> \/&gt;\n<\/span><\/span><span style=\"display:flex;\"><span>    &lt;\/<span style=\"color:#f92672\">div<\/span>&gt;\n<\/span><\/span><span style=\"display:flex;\"><span>  );\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ Counter.tsx\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span><span style=\"color:#66d9ef\">export<\/span> <span style=\"color:#66d9ef\">default<\/span> <span style=\"color:#66d9ef\">function<\/span> <span style=\"color:#a6e22e\">Counter() {<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">const<\/span> [<span style=\"color:#a6e22e\">count<\/span>, <span style=\"color:#a6e22e\">setCount<\/span>] <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">useState<\/span>(<span style=\"color:#ae81ff\">0<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">return<\/span> (\n<\/span><\/span><span style=\"display:flex;\"><span>    &lt;<span style=\"color:#f92672\">div<\/span> <span style=\"color:#a6e22e\">className<\/span><span style=\"color:#f92672\">=<\/span><span style=\"color:#e6db74\">&#34;counter&#34;<\/span>&gt;\n<\/span><\/span><span style=\"display:flex;\"><span>      &lt;<span style=\"color:#f92672\">button<\/span> <span style=\"color:#a6e22e\">onClick<\/span><span style=\"color:#f92672\">=<\/span>{() <span style=\"color:#f92672\">=&gt;<\/span> <span style=\"color:#a6e22e\">setCount<\/span>(<span style=\"color:#a6e22e\">count<\/span> <span style=\"color:#f92672\">+<\/span> <span style=\"color:#ae81ff\">1<\/span>)}&gt;<span style=\"color:#a6e22e\">Increment<\/span>&lt;\/<span style=\"color:#f92672\">button<\/span>&gt;\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>      &lt;<span style=\"color:#f92672\">p<\/span>&gt;<span style=\"color:#a6e22e\">The<\/span> <span style=\"color:#a6e22e\">value<\/span> <span style=\"color:#66d9ef\">is<\/span><span style=\"color:#f92672\">:<\/span> {<span style=\"color:#a6e22e\">count<\/span>}&lt;\/<span style=\"color:#f92672\">p<\/span>&gt;\n<\/span><\/span><span style=\"display:flex;\"><span>    &lt;\/<span style=\"color:#f92672\">div<\/span>&gt;\n<\/span><\/span><span style=\"display:flex;\"><span>  );\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p>Assuming the <code>count<\/code>&rsquo;s value is <code>7<\/code>, this is what the <code>FiberTree<\/code> would look like:<\/p>\n<p><p class=\"markdown-image\">\n  <img src=\"images\/fiber-tree-initial.png\" alt=\"fiber-tree-initial.png\"  \/>\n<\/p><\/p>\n<p>It is implied that the relationships indicated by the arrows(e.g. <em>child, parent, sibling<\/em>) apply on <code>FiberNode<\/code>s of the same type(i.e. a <code>current<\/code> <code>FiberNode<\/code> is a child of another <code>current<\/code> <code>FiberNode<\/code>, <strong>not<\/strong> <code>workInProgress<\/code>).<\/p>\n<p>Notice the <strong>old<\/strong> <code>workInProgress<\/code> <code>FiberNode<\/code>s(highlighted in grey and abbreviated as <em>OLD WIP<\/em>) - what it is saying is that, prior to what\u2019s currently being shown in the browser, the <code>count<\/code>\u2019s value was <code>6<\/code> and the <strong>new<\/strong> <code>workInProgress<\/code> came with the value of <code>7<\/code>. Then, <code>workInProgress<\/code> became the current <code>current<\/code>. As a result, in the situation depicted by the above diagram, <code>current === OLD_WIP<\/code> is <code>true<\/code>. <em>OLD WIP<\/em> doesn\u2019t do anything per se, it\u2019s just a placeholder for a potential <code>workInProgress<\/code> <code>FiberNode<\/code> that may come with a new value.<\/p>\n<p>Now, let\u2019s see what happens if the <code>Increment<\/code> button is clicked. Firstly, an event will be triggered as a result of pressing the button and then the <code>useState<\/code>&rsquo;s <em>dispatcher<\/em>(i.e. the <code>setCount()<\/code> function) will be invoked. This event signals that <em><strong>some synchronization work<\/strong><\/em> needs to be done on the <code>FiberTree<\/code>. It is called <em>synchronization<\/em> because the <code>current<\/code> tree needs to take in the changes carried by the <code>workInProgress<\/code> tree, so that in the end the results are visible in the browser.<\/p>\n<p><p class=\"markdown-image\">\n  <img src=\"images\/fiber-tree-set-count.png\" alt=\"fiber-tree-set-count.png\"  \/>\n<\/p><\/p>\n<p>The <code>Counter<\/code> has been highlighted in red because it\u2019s where the <code>useState<\/code> hook has been used. It\u2019s also the topmost node that would be affected by a state change(since it holds the state), so any updates could affect only the state of its children elements(e.g. the <code>p<\/code> element which displays the <code>count<\/code>&rsquo;s value). Put differently, by invoking <code>setCount()<\/code>, the <code>Counter<\/code> component becomes the cause of a re-render of the <code>FiberTree<\/code>.<\/p>\n<p>What happens next is that the <strong>branch<\/strong>\/<strong>subtree<\/strong> of nodes which starts from the root and includes the <code>Counter<\/code>&rsquo;s <code>FiberNode<\/code>s is marked as <em>dirty<\/em>(marked with red hachures)<em>:<\/em><\/p>\n<p><p class=\"markdown-image\">\n  <img src=\"images\/fiber-tree-marked-as-dirty.png\" alt=\"fiber-tree-marked-as-dirty.png\"  \/>\n<\/p><\/p>\n<p>Marking those ancestor nodes as <em>dirty<\/em> indicates that <strong>something has changed<\/strong> somewhere down in the tree. This has further implications - by setting apart a subtree that contains modifications, we can <strong>avoid<\/strong> doing redundant work on branches that are not affected at all. For example, the <code>FiberNode<\/code>s associated with the <code>&lt;i&gt;<\/code> tag will not be influenced by the <code>Counter<\/code>&rsquo;s state. Let\u2019s see the next diagram, which underlines the presence of <code>workInProgress<\/code> nodes:<\/p>\n<p><p class=\"markdown-image\">\n  <img src=\"images\/fiber-tree-wip.png\" alt=\"fiber-tree-wip.png\"  \/>\n<\/p><\/p>\n<p>Notice how the <code>FiberNode<\/code> corresponding to the <code>&lt;i&gt;<\/code> tag is <em>skipped,<\/em> because the changes that occurred have no effect on it. If such <code>FiberNode<\/code> had had any children, the entire subtree would\u2019ve been skipped. As you can see, a <code>workInProgress<\/code> node has been set for <strong>each node in the entire <em>modified<\/em> subtree<\/strong>(including <code>Counter<\/code>&rsquo;s descendants - so modifications can be discovered). Although not every <code>workInProgress<\/code> node may bring new updates, it\u2019s necessary to be able to identify the subtree which brought modifications. This comes handy especially during the <strong>commit phase<\/strong>, where all the changes will be applied to the real DOM.<\/p>\n<p>Also, take note of the fact that the <code>p<\/code>&rsquo;s <code>workInProgress<\/code> node contains the most recent value of the <code>counter<\/code>, which is <code>8<\/code>.<\/p>\n<p>Now, you might be wondering why a <code>workInProgress<\/code> node has been set for <code>h2<\/code> as well(which clearly isn\u2019t affected at all by the <code>Counter<\/code>&rsquo;s state) - the reason is that its parent, the <code>div<\/code>&rsquo;s <code>FiberNode<\/code>, is part of the subtree which contains a changes and, when this happens, a parent <code>FiberNode<\/code> will set <code>workInProgress<\/code> nodes for all its children. Concretely, the <code>div<\/code>&rsquo;s <code>FiberNode<\/code> has created a <code>workInProgress<\/code> node for each of <code>h2<\/code> and <code>Counter<\/code>. Another way to think about this is because <code>div<\/code>&rsquo;s <code>FiberNode<\/code> is marked as dirty, it means that, somewhere among its descendants, a modification has occurred. Since it can\u2019t know beforehand where exactly it took place, all the <code>div'<\/code>s direct descendants will get a new <code>workInProgress<\/code> <code>FiberNode<\/code>. This doesn\u2019t seem to provoke any issues, since the subtree which has <code>h2<\/code> as root will be skipped either way.<\/p>\n<p>However, if a <code>workInProgress<\/code> node has been created, it doesn\u2019t necessarily have to bring updates. It <strong>may be just part of a branch<\/strong>\/<strong>subtree<\/strong> in which updates have been made. This can be observed in the following diagram:<\/p>\n<p><p class=\"markdown-image\">\n  <img src=\"images\/fiber-tree-updates.png\" alt=\"fiber-tree-updates.png\"  \/>\n<\/p><\/p>\n<blockquote>\n<p>What is shown above is the moment after the changes have been committed to the real DOM.<\/p>\n<\/blockquote>\n<p>Let\u2019s now go step by step and understand why each of the nodes coloured in blue brought changes:<\/p>\n<ul>\n<li><code>p<\/code> - it displays the <code>count<\/code>&rsquo;s value, so obviously its content has been changed<\/li>\n<li><code>button<\/code> - it has been used like this in our component: <code>&lt;button onClick={() =&gt; setCount(count + 1)}&gt;...&lt;\/button&gt;<\/code>. This means that a new function will be created each time the <code>Counter<\/code> component renders. And since a change in the state occurred, we know for sure the component re-rendered and therefore the <code>button<\/code> element has received a <strong>new prop<\/strong><\/li>\n<li><code>div.counter<\/code> - its parent node(i.e. <code>Counter<\/code>) re-rendered and its children are different(i.e. its <code>p<\/code> child previously displayed <code>7<\/code> and now it displays <code>8<\/code>); <a href=\"https:\/\/github.com\/indepth-dev\/community\/discussions\/264#discussioncomment-4089979\" target=\"_blank\" rel=\"noopener\">here<\/a> is a discussion that might clear up some possible confusions regarding this aspect<\/li>\n<li><code>Counter<\/code> - its state(from <code>useState<\/code>) changed<\/li>\n<\/ul>\n<blockquote>\n<p>As a side note, if there was a static element inside the <code>Counter<\/code> component, like <code>&lt;h3&gt;hello&lt;\/h3&gt;<\/code>, it would\u2019ve been different across re-renders of <code>Counter<\/code>. That\u2019s because React elements are essentially objects resulted from calling <a href=\"https:\/\/github.com\/facebook\/react\/blob\/v18.0.0\/packages\/react\/src\/ReactElement.js#L362\" target=\"_blank\" rel=\"noopener\"><code>createElement()<\/code><\/a>. So, re-rendering <code>Counter<\/code> involves re-calling that <code>createElement<\/code> and hence a new object will be returned every time.<\/p>\n<\/blockquote>\n<p>And now, since all the changes have been committed, the <code>FiberTree<\/code> is back to its <em>stable<\/em> state:<\/p>\n<p><p class=\"markdown-image\">\n  <img src=\"images\/fiber-tree-final.png\" alt=\"fiber-tree-final.png\"  \/>\n<\/p><\/p>\n<blockquote>\n<p>Notice how the <code>count<\/code>&rsquo;s value is now <code>8<\/code>.<\/p>\n<\/blockquote>\n<p>As a side note, another interesting facet of the <code>alternate<\/code> property is that is allows React to keep track of 2 separate trees simultaneously. You can distinguish the <code>current<\/code> tree by following the green rectangles and the <code>workInProgress<\/code> tree by following the orange ones. What\u2019s also worth mentioning is that these aforementioned trees don\u2019t have to be symmetrical - one can have more or less nodes compared to the other(e.g. when elements are added\/removed). We will explore such cases in upcoming articles.<\/p>\n<h2 id=\"conclusion\">\n  <span>\n  Conclusion\n  <\/span>\n  <a href=\"#conclusion\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><p>It would be unfair to say this article was just the tip of the iceberg, because I believe we actually covered many fundamental aspects of the React\u2019s <em>virtual DOM.<\/em> Of course, some details have been omitted for the sake of simplicity, but I hope the bits of knowledge acquired from this writing will make you more aware of what\u2019s going on under the hood and, why not, give you enough confidence to start exploring the source code on your own.<\/p>\n<p><strong>To do a quick recap<\/strong>: the main unit of React\u2019s <em>virtual DOM<\/em> is the <code>FiberNode<\/code>. With the help of its <code>alternate<\/code> property, React can discover what changes have been made inside the application. It does that by <strong>comparing<\/strong> the <strong>current state<\/strong>(what\u2019s visible at this moment in the browser - stored in the <code>current<\/code> tree) and the <strong>newly updated state<\/strong>(what\u2019s to be shown in the browser - stored in the <code>workInProgress<\/code> tree). One <code>current<\/code> <code>FiberNode<\/code> can access its counterpart <code>workInProgress<\/code> <code>FiberNode<\/code>(and vice versa) via the <code>alternate<\/code> property. Once all changes have been discovered, they are all committed at once on the real DOM and, after that, the outcomes can be seen in the browser.<\/p>\n<p><strong>Thanks for reading!<\/strong><\/p>\n"},{"title":"Why component identifiers must be capitalized in React","link":"https:\/\/andreigatej.dev\/blog\/why-component-identifiers-must-be-capitalized-in-react\/","pubDate":"Thu, 07 Apr 2022 00:00:00 +0000","guid":"https:\/\/andreigatej.dev\/blog\/why-component-identifiers-must-be-capitalized-in-react\/","description":"<p><em>This article has been published on <a href=\"https:\/\/indepth.dev\/posts\/1499\/why-component-identifiers-must-be-capitalized-in-react\" target=\"_blank\" rel=\"noopener\">indepth.dev<\/a>.<\/em><\/p>\n<h2 id=\"introduction\">\n  <span>\n  Introduction\n  <\/span>\n  <a href=\"#introduction\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><p>In this short article, I\u2019d like to share some findings as to why a component must be used as <code>&lt;Foo \/&gt;<\/code>(capitalized), as opposed to <code>&lt;foo \/&gt;<\/code>. It may not occur very often(may not even be recommended), but if you import a component like <code>import foo from '.\/Foo'<\/code> and use it as <code>&lt;foo \/&gt;<\/code>, React will not be happy with that:<\/p>\n<p><p class=\"markdown-image\">\n  <img src=\"images\/Untitled-1.png\" alt=\"Content image\"  \/>\n<\/p><\/p>\n<p><em>You can quickly see this in action in <a href=\"https:\/\/codesandbox.io\/s\/busy-proskuriakova-npp9gj?file=\/src\/App.js\" target=\"_blank\" rel=\"noopener\">this CodeSandbox app<\/a>.<\/em><\/p>\n<p>In other words, <code>&lt;foo \/&gt;<\/code> is considered a DOM element and the <code>foo<\/code> DOM element does not actually exist, hence the error. Although the fix is straightforward, another thing sparked my interest: <em>how exactly is decided that <code>&lt;Foo \/&gt;<\/code> should be a component and <code>&lt;foo \/&gt;<\/code> a DOM element?<\/em><\/p>\n<p>In the rest of the article we will briefly talk about the Babel and then we will reveal the answer to that question.<\/p>\n<h2 id=\"how-babel-works-at-a-high-level\">\n  <span>\n  How Babel works at a high level\n  <\/span>\n  <a href=\"#how-babel-works-at-a-high-level\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><p>As you might know, Babel is the tool responsible, among other things, for converting JSX into syntax which is comprehensible for the browser. It does that through a number of plugins, but the one of interest for now is <a href=\"https:\/\/github.com\/babel\/babel\/tree\/main\/packages\/babel-plugin-transform-react-jsx\" target=\"_blank\" rel=\"noopener\"><code>@babel\/plugin-transform-react-jsx<\/code><\/a>.<\/p>\n<p>Here is a diagram that partially covers the Babel\u2019s compiling process:<\/p>\n<p><p class=\"markdown-image\">\n  <img src=\"images\/Untitled-1-1.png\" alt=\"Untitled\"  \/>\n<\/p><\/p>\n<p><em>The corresponding link for the above diagram can be found <a href=\"https:\/\/excalidraw.com\/#json=n0ipIimqsZJ1gtZVNiB--,mfHwERMjPGsFDvAbdjVuXw\" target=\"_blank\" rel=\"noopener\">here<\/a>.<\/em><\/p>\n<p>So, Babel will take the initial source code as a raw string and then it will build the corresponding AST which all sorts of plugins will be applied on. For example, here we can see the plugin we mentioned earlier, <code>transform-react-jsx<\/code>:<\/p>\n<p><p class=\"markdown-image\">\n  <img src=\"images\/Untitled-2.png\" alt=\"Untitled\"  \/>\n<\/p><\/p>\n<p>In the image above, the <code>transformFile<\/code> function refers to the <strong>second phase<\/strong> of the previous diagram - it\u2019s where all the selected plugins are applied on the <em>raw<\/em> AST.<\/p>\n<p>The way the <code>transform-react-jsx<\/code> plugin works is that it comes with some <strong>functions<\/strong> to be invoked when <strong>certain AST nodes are visited<\/strong>. For example, here is what happens when a <code>JSXElement<\/code> node has been visited:<\/p>\n<p><p class=\"markdown-image\">\n  <img src=\"images\/Untitled-3.png\" alt=\"Untitled\"  \/>\n<\/p><\/p>\n<blockquote>\n<p>The <code>exit<\/code> function can be thought of as a <em>visiting hook.<\/em> Its complement is the <code>enter<\/code> function, which is called when a node is about to be visited. After <code>enter<\/code>, the current AST node\u2019s children are visited and, after that, the <code>exit<\/code> function is called for that node. To put it another way: <code>Node.enter()<\/code> \u2192 visited children \u2192 <code>Node.exit()<\/code>.<\/p>\n<\/blockquote>\n<p>In the image above, we are at the <code>&lt;Foo \/&gt;<\/code> part. As you can notice, the <code>JSXElement<\/code> has an <code>JSXOpeningElement<\/code> which, for its part, has a name(i.e. <code>JSXIdentifier<\/code>). What also happens <strong>at this step<\/strong> is to decide what really <code>Foo<\/code> refers to - <em>does it refer to a <strong>component<\/strong> or just another <strong>DOM element<\/strong>?<\/em> This decision has to be made because in JSX we can write <code>&lt;div&gt;&lt;\/div&gt;<\/code>, as well <code>&lt;CustomComponent&gt;&lt;\/CustomComponent&gt;<\/code> - at some point, Babel has to choose what actually a <code>JSXElement<\/code> is and, later on, React will <em>react<\/em> accordingly.<\/p>\n<p>Calling <code>JSXElement.exit()<\/code> will eventually lead to calling the <code>getTag<\/code> function, which is the place where the question stated at the beginning finds its answer:<\/p>\n<p><p class=\"markdown-image\">\n  <img src=\"images\/Untitled-4.png\" alt=\"Untitled\"  \/>\n<\/p><\/p>\n<p>The <code>getTag<\/code> function will return a <strong>string literal<\/strong>(e.g. <code>\u201cdiv\u201d<\/code>, <code>\u201cfoo\u201d<\/code> if used as <code>&lt;foo \/&gt;<\/code>) if the <code>tagName<\/code> starts with a lowercase letter(i.e. <code>\/^[a-z]\/<\/code>). So, if <code>&lt;Foo \/&gt;<\/code> is used, the result will be:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span>{\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">type<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#34;Identifier&#34;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">start<\/span>: <span style=\"color:#66d9ef\">165<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">end<\/span>: <span style=\"color:#66d9ef\">168<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">name<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#34;Foo&#34;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#75715e\">\/* ... *\/<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p>and, on the other hand, if <code>&lt;foo \/&gt;<\/code> is used:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span>{\n<\/span><\/span><span style=\"display:flex;\"><span>\t<span style=\"color:#66d9ef\">type<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#34;StringLiteral&#34;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>\t<span style=\"color:#a6e22e\">value<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;foo&#39;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p>The fundamental difference between an <code>Identifier<\/code> and a <code>StringLiteral<\/code> is that the former will end up in <code>createElement(componentName)<\/code> and the latter in <code>createElement('componentName')<\/code>(take note of the quotes). React will then choose different paths <strong>depending on the element\u2019s type.<\/strong><\/p>\n<h2 id=\"conclusion\">\n  <span>\n  Conclusion\n  <\/span>\n  <a href=\"#conclusion\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><p>Before starting to explore some of the things that Babel does under the hood, I had expected that there must be a check somewhere that indicates whether <code>JSXElement<\/code> actually refers to a component identifier or not, but I had not idea where that check was located.<\/p>\n<p>In the end, the answer to my question turned out to be the <code>isCompatTag<\/code> function. Even if I had known this beforehand, I would\u2019ve needed some more context about that function - so, exploring a bit how Babel works not only made things more clearer to me, but also exposed me to other interesting aspects of the entire compiling process(which I will hopefully write about in the future).<\/p>\n<p><strong>Thanks for reading!<\/strong><\/p>\n"},{"title":"Webpack: An in-depth introduction to SplitChunksPlugin","link":"https:\/\/andreigatej.dev\/blog\/webpack-splitchunksplugin\/","pubDate":"Mon, 21 Feb 2022 00:00:00 +0000","guid":"https:\/\/andreigatej.dev\/blog\/webpack-splitchunksplugin\/","description":"<p><em>This article has been published on <a href=\"https:\/\/indepth.dev\/posts\/1490\/webpack-an-in-depth-introduction-to-splitchunksplugin\" target=\"_blank\" rel=\"noopener\">indepth.dev<\/a>.<\/em><\/p>\n<h2 id=\"introduction\">\n  <span>\n  Introduction\n  <\/span>\n  <a href=\"#introduction\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><p>If the name of this plugin doesn&rsquo;t sound familiar, it may be due to the fact that it is <em>disguised as<\/em> the <code>optimization.splitChunks<\/code> configuration option. If that doesn&rsquo;t look very familiar either, then you probably haven&rsquo;t worked on build configuration much. Regardless of whether you have encountered the name of the plugin or not, this article will give you a good introduction to one of the most used plugins in webpack&rsquo;s ecosystem.<\/p>\n<p>This is a rather complex topic, so this article aims to be a foundation for future articles since it goes over the main building blocks of the plugin, with the help of digestible diagrams and StackBlitz demos.<\/p>\n<p>As we will see, a problem this plugin solves is <strong>code duplication<\/strong>, which can lead to redundant content loaded over the network. <code>SplitChunkPlugin<\/code> is able to figure out, based on some configuration, the modules which are too <em>expensive<\/em> to be duplicated and then put them in separate chunks so that the considerable efforts of loading large modules are done only once.<\/p>\n<p>A few webpack-related articles that you might find interesting, although they are not required to understand for this write-up:<\/p>\n<ul>\n<li><a href=\"https:\/\/andreigatej.dev\/blog\/webpack-bundling-process\/\">An in-depth perspective on webpack&rsquo;s bundling process<\/a><\/li>\n<li><a href=\"https:\/\/andreigatej.dev\/blog\/webpack-import-function-dynamic-arguments\/\">Demystifying webpack&rsquo;s &lsquo;import&rsquo; function: using dynamic arguments<\/a><\/li>\n<\/ul>\n<p>It is highly recommended to follow along by experimenting on the provided StackBlitz demos.<\/p>\n<p>Let&rsquo;s get started!<\/p>\n<p><em>I&rsquo;ve used lots of StackBlitz examples in this article to demonstrate notions. However, I noticed that files in the <code>node_modules<\/code> folder don&rsquo;t persist across page refreshes and since we will need such files in this article, each StackBlitz demo will detail in its <code>readme<\/code> file the required steps to get the app up and running.<\/em><\/p>\n<h2 id=\"setting-up\">\n  <span>\n  Setting up\n  <\/span>\n  <a href=\"#setting-up\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><p>In order to get a better understanding of what this plugin is capable of, throughout this article we will be using an example which will undergo, as we go along, different configuration-wise changes \u00a0that demonstrate this plugin&rsquo;s features.<\/p>\n<p>Before we introduce the problem this plugin solves, let&rsquo;s first see the small project along with its configuration which will mark the start of this learning journey:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-markdown\" data-lang=\"markdown\"><span style=\"display:flex;\"><span>\u251c\u2500\u2500 a.js\n<\/span><\/span><span style=\"display:flex;\"><span>\u251c\u2500\u2500 b.js\n<\/span><\/span><span style=\"display:flex;\"><span>\u251c\u2500\u2500 c.js\n<\/span><\/span><span style=\"display:flex;\"><span>\u251c\u2500\u2500 d.js\n<\/span><\/span><span style=\"display:flex;\"><span>\u251c\u2500\u2500 e.js\n<\/span><\/span><span style=\"display:flex;\"><span>\u251c\u2500\u2500 f.js\n<\/span><\/span><span style=\"display:flex;\"><span>\u251c\u2500\u2500 g.js\n<\/span><\/span><span style=\"display:flex;\"><span>\u251c\u2500\u2500 index.js\n<\/span><\/span><span style=\"display:flex;\"><span>\u251c\u2500\u2500 node_modules\n<\/span><\/span><span style=\"display:flex;\"><span>\u2502   \u251c\u2500\u2500 x.js\n<\/span><\/span><span style=\"display:flex;\"><span>\u2502   \u251c\u2500\u2500 y.js\n<\/span><\/span><span style=\"display:flex;\"><span>\u2502   \u2514\u2500\u2500 z.js\n<\/span><\/span><span style=\"display:flex;\"><span>\u2514\u2500\u2500 webpack.config.js\n<\/span><\/span><\/code><\/pre><\/div><p><em>This project can be found in this <a href=\"https:\/\/stackblitz.com\/edit\/node-qaj9rk?file=readme.md\" target=\"_blank\" rel=\"noopener\">StackBlitz application<\/a>. Make sure you follow the instructions listed in <code>readme<\/code>.<\/em><\/p>\n<p>The <code>webpack.config.js<\/code> file looks as follows:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-typescript\" data-lang=\"typescript\"><span style=\"display:flex;\"><span>{\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">mode<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;production&#39;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">entry<\/span><span style=\"color:#f92672\">:<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">main<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;.\/src&#39;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  },\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">output<\/span><span style=\"color:#f92672\">:<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">path<\/span>: <span style=\"color:#66d9ef\">path.join<\/span>(<span style=\"color:#a6e22e\">__dirname<\/span>, <span style=\"color:#e6db74\">&#39;dist&#39;<\/span>),\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">filename<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;[name].js&#39;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">clean<\/span>: <span style=\"color:#66d9ef\">true<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  },\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">optimization<\/span><span style=\"color:#f92672\">:<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#75715e\">\/\/ Instruct webpack not to obfuscate the resulting code\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>    <span style=\"color:#a6e22e\">minimize<\/span>: <span style=\"color:#66d9ef\">false<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">splitChunks<\/span>: <span style=\"color:#66d9ef\">false<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  },\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">context<\/span>: <span style=\"color:#66d9ef\">__dirname<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>};\n<\/span><\/span><\/code><\/pre><\/div><p>After the <code>npm run build<\/code> has been run in the StackBlitz app, the <code>dist<\/code> directory should have the following structure:<\/p>\n<p><p class=\"markdown-image\">\n  <img src=\"images\/output-dir-before-first-diagram.png\" alt=\"output-dir-before-first-diagram.png\"  \/>\n<\/p><\/p>\n<p>Notice there are 5 chunks, 1 for the single item in the <code>entry<\/code> object(i.e. <code>main: '.\/src'<\/code>) and 4 chunks that resulted from using the <code>import()<\/code> function.<\/p>\n<p>This is a diagram that describes not only the relationship between modules(the dependant and the dependencies), but also the parent-child relationships between <strong>chunks:<\/strong><\/p>\n<p><p class=\"markdown-image\">\n  <img src=\"images\/file-structure.png\" alt=\"file-structure.png\"  \/>\n<\/p><\/p>\n<p><em>The link for the above diagram can be found <a href=\"https:\/\/excalidraw.com\/#json=VDeCLP274PUk7GR8KS8N0,epOXJ2Y-EPPOXQzirAnXfQ\" target=\"_blank\" rel=\"noopener\">here<\/a>.<\/em><\/p>\n<p>My recommendation would be to open that diagram&rsquo;s link and try to understand a bit what the diagram illustrates.<br>\nThe black arrows indicate the use of top level ES module <strong>import statements<\/strong>(i.e. <code>import xDefault from 'x'<\/code>), the purple arrows, as described on the arrows themselves, show the use of the <strong>import function<\/strong>(i.e. <code>import(\/* webpackChunkName: &quot;async-a&quot; *\/ '.\/a')<\/code>) and this has a very important consequence: the <strong>creation of new chunks<\/strong>. Last but not least, the chunks are framed in green blocks. The green nested frames indicate a parent-child relationship between chunks.<\/p>\n<p>As in, the <code>main<\/code> chunk has 3 child chunks: <code>async-a<\/code>, <code>async-b<\/code> and <code>async-c<\/code>. The <code>async-a<\/code> chunk has a child chunk too, <code>async-g<\/code>. It is also important to mention that modules(framed in blue) belong <strong>only<\/strong> to the chunk described by the chunk&rsquo;s green frame. So, the <code>g<\/code> and <code>f<\/code> modules belong to the <code>async-g<\/code> chunk.<\/p>\n<p>Now that we have some basic concepts in place, let&rsquo;s start exploring!<\/p>\n<h2 id=\"introducing-the-problem\">\n  <span>\n  Introducing the problem\n  <\/span>\n  <a href=\"#introducing-the-problem\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><p>Before going any further, I&rsquo;d recommend you run the project&rsquo;s build script. <a href=\"https:\/\/stackblitz.com\/edit\/node-qaj9rk?file=readme.md\" target=\"_blank\" rel=\"noopener\">Here<\/a> is once again a link to the StackBlitz app in question. We will use the results yielded in the <code>dist<\/code> directory in order to make the first steps towards understanding the problem.<\/p>\n<p>Let&rsquo;s spend a little time on examining the contents of <code>dist<\/code>. As you can see, there are 5 files, so our project is composed of <strong>5 chunks<\/strong>. The <code>main<\/code> chunk is literally the <em>main chunk<\/em>(it can be thought of as the <em>entry point<\/em> of our app) and this can be noticed from its source code - it contains a lot of webpack\u2019s <em>runtime code<\/em> which holds the logic for loading other chunks(e.g. via HTTP), for storing the modules and much more. If you peek into the <code>async-*<\/code> files, you should see that there just a small amount of runtime code required to <em>connect<\/em> these chunks with the <em>main chunk<\/em>. Most of the code in an <code>async-*.js<\/code> file is for the imported modules and the exported members.<\/p>\n<p>Let\u2019s think about this interesting question: how many times do you think the <code>x<\/code> module(that corresponds to the <code>x.js<\/code> file and is imported into the <code>a<\/code>, <code>b<\/code> and <code>c<\/code> modules) will be <strong>copied<\/strong> in all these 5 resulting files? Feel free to refer to the diagram. In order to find the answer to this question, you can copy the exported string from the <code>x.js<\/code> file and perform a <em>global search<\/em> in the StackBlitz app:<\/p>\n<p><p class=\"markdown-image\">\n  <img src=\"images\/nr-times-x.png\" alt=\"nr-times-x.png\"  \/>\n<\/p><\/p>\n<p>So, we can conclude that the <code>x.js<\/code>&rsquo;s content is <strong>duplicated<\/strong> 3 times, one time for each importing module that makes a separate async chunk(e.g. the <code>a<\/code> module which corresponds to the <code>async-a<\/code> chunk, <code>b<\/code> to <code>async-b<\/code> and <code>c<\/code> to <code>async-c<\/code>). Imagine now if the <code>x.js<\/code> file had hundreds of lines of code! All these lines would be copied in 3 different places - this seems like a waste of resources. It&rsquo;s true that this fact <strong>won&rsquo;t cause the <code>x<\/code> module to be executed multiple times by webpack<\/strong>, so in the end we will still end up having <strong>only one instance<\/strong> of <code>x.js<\/code> in our app.<\/p>\n<p>However, recall what fetching a chunk implies - an HTTP request. Since <code>x.js<\/code>&rsquo;s content is present in 3 chunks, if we first load, let&rsquo;s say, the <code>async-a<\/code> chunk, then the entire code that&rsquo;s in the <code>async-a.js<\/code> file will have to be downloaded from the network and then parsed. If the <code>x.js<\/code> file is considerably large, this <em>loading process<\/em> may take a significant amount of time to complete. Having to go through this <em>lengthy<\/em> process another 2 times doesn&rsquo;t look like the best approach we can take, so there must be a better way.<\/p>\n<p>Here&rsquo;s a way to visualise this problem with the help of a diagram:<\/p>\n<p><p class=\"markdown-image\">\n  <img src=\"images\/x-copied-red_-1-.png\" alt=\"x-copied-red (1).png\"  \/>\n<\/p><\/p>\n<p><em>A link for the above diagram can be found <a href=\"https:\/\/excalidraw.com\/#json=bFTaPCAN9LmDknlCO8GHd,IJSaYsdghgf3SkCNiGhiAQ\" target=\"_blank\" rel=\"noopener\">here<\/a>.<\/em><\/p>\n<p>This diagram is not very different from the first one, since it only highlights the <code>x<\/code> module in red. This simply indicates that there is something <em>wrong<\/em> with this module and it will also help us identify what <code>SplitChunksPlugin<\/code> does in order to solve this problem. This is what the next section is about.<\/p>\n<blockquote>\n<p>As you might have noticed, it is true that modules such as <code>f<\/code>, <code>d<\/code>, <code>y<\/code> are in the same situation as <code>x<\/code>, but we are only focusing on <code>x<\/code> now, for simplicity&rsquo;s sake.<\/p>\n<\/blockquote>\n<h2 id=\"how-splitchunksplugin-solves-the-problem\">\n  <span>\n  How <code>SplitChunksPlugin<\/code> solves the problem\n  <\/span>\n  <a href=\"#how-splitchunksplugin-solves-the-problem\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><p>I assume you must be anxious to dive deep into the webpack configuration so that we can see what <code>SplitChunksPlugin<\/code>can do, but let&rsquo;s first think of how we could solve this problem conceptually. In other words, after consulting the above diagram, how would you optimise the current situation? Supposing that <code>x.js<\/code> has 1000 lines of code, our app will have to load them 3 times(because <code>x<\/code> is part of 3 <strong>different chunks<\/strong>, each of which being requested via <code>import()<\/code> from the <code>main<\/code> chunk). I should also mention that if <strong>the same chunk<\/strong> is requested multiple times, <strong>only one<\/strong> HTTP request will be made and then its modules will be added to a cache object, such that, on subsequent requests for that chunk, everything will be retrieved directly from that cache object.<\/p>\n<p>Considering the above information, we could load the 1000 lines of code <strong>only once<\/strong> by placing the <code>x<\/code> module in a new chunk. This way, when module <code>x<\/code> is required by module <code>a<\/code>, an HTTP request will be made in order to load the chunk in which <code>x<\/code> resides in(this is because the chunk is loaded for the first time). Then, when module <code>b<\/code> requires <code>x<\/code>, those 1000 lines of code <strong>won&rsquo;t be loaded again<\/strong> and <code>x<\/code> will be retrieved directly from memory. The same happens when the <code>c<\/code> module requires <code>x<\/code>.<\/p>\n<p>Let&rsquo;s see how this solution would look fit in a diagram:<\/p>\n<p><p class=\"markdown-image\">\n  <img src=\"images\/x-in-separate-chunk_-1-.png\" alt=\"x-in-separate-chunk (1).png\"  \/>\n<\/p><\/p>\n<p><em>A link for the above diagram can be found <a href=\"https:\/\/excalidraw.com\/#json=d8yNHnplA4Bo3Q3AziqYQ,V_p8VsRBKjU2Z9jvOya_Cg\" target=\"_blank\" rel=\"noopener\">here<\/a>.<\/em><\/p>\n<p>The barely visible red rectangles represent the <em>replacements<\/em> that have been made. Now, because the <code>x<\/code> module is in a separate chunk, it will be <strong>loaded only once<\/strong> across the network, no matter how many times the module is requested. This is what we can achieve by using \u00a0<code>SplitChunksPlugin<\/code>.<\/p>\n<p>Now, let&rsquo;s come back to our favourite part: webpack configuration. This is what the <code>webpack.config.js<\/code> file should look like in order to <em>activate<\/em> <code>SplitChunksPlugin<\/code> with the default options:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span>{\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">mode<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;production&#39;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">entry<\/span><span style=\"color:#f92672\">:<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">main<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;.\/src&#39;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  },\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">output<\/span><span style=\"color:#f92672\">:<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">path<\/span>: <span style=\"color:#66d9ef\">path.join<\/span>(<span style=\"color:#a6e22e\">__dirname<\/span>, <span style=\"color:#e6db74\">&#39;dist&#39;<\/span>),\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">filename<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;[name].js&#39;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">clean<\/span>: <span style=\"color:#66d9ef\">true<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  },\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">optimization<\/span><span style=\"color:#f92672\">:<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#75715e\">\/\/ Instruct webpack not to obfuscate the resulting code\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>    <span style=\"color:#a6e22e\">minimize<\/span>: <span style=\"color:#66d9ef\">false<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">splitChunks<\/span><span style=\"color:#f92672\">:<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#a6e22e\">minSize<\/span>: <span style=\"color:#66d9ef\">0<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>    },\n<\/span><\/span><span style=\"display:flex;\"><span>  },\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">context<\/span>: <span style=\"color:#66d9ef\">__dirname<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p><em>This solution can be found in <a href=\"https:\/\/stackblitz.com\/edit\/node-tlym1w?file=readme.md\" target=\"_blank\" rel=\"noopener\">this StackBlitz app<\/a>(make sure to follow the instructions from the <code>readme<\/code> file).<\/em><\/p>\n<p>The <code>minSize<\/code> option isn&rsquo;t very relevant now, but we needed it because the chunk which <code>x<\/code> belongs to is quite small and webpack would think it&rsquo;s not worth it creating a new chunk just for a few bytes. So, we&rsquo;re telling <code>SplitChunksPlugin<\/code> to create a new chunk if its total number of bytes is greater than or equal to 0.<\/p>\n<p>As a side note, the <code>x<\/code> module is not the only module which can belong to this new chunk, there can be others too. The grouping criterion is how the modules are used in other chunks. If, for example, besides <code>x<\/code>, there were a module <code>w<\/code> used the same as <code>x<\/code>, then the separate chunk would contain both <code>x<\/code> and <code>w<\/code> modules.<\/p>\n<p>The configuration options the <code>SplitChunksPlugin<\/code> takes in determine how and whether or not new chunks are created. In order for a chunk to be created, it must, first of all, abide by a set of rules which defines a so-called <strong>cache group<\/strong>.<\/p>\n<p>For instance, we could say: <em>I&rsquo;d want chunks to be created only from modules which come from <code>node_modules<\/code> and the chunks they form must have at least 1000 bytes.<\/em> We could also enforce the number of existing chunks a module appears in to be at least <code>N<\/code>. In the example we&rsquo;ve been following, we could prevent any chunks from being created if the <code>x<\/code> module does not appear in at least 3 chunks.<\/p>\n<p><strong>All such constraints could define a cache group and only chunks that fulfil all the cache group&rsquo;s conditions will be created.<\/strong><\/p>\n<p>In the following sections, we will examine the configuration options that are available for <code>SplitChunksPlugin<\/code>, starting off with arguably one of the least intuitive of them.<\/p>\n<h2 id=\"the-cachegroup-option\">\n  <span>\n  The <code>cacheGroup<\/code> option\n  <\/span>\n  <a href=\"#the-cachegroup-option\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><p>To reiterate what has been mentioned at the end of the previous section, a <strong>cache group<\/strong> is described by a set of rules. This set of rules defines the circumstances in which new chunks can be created. Let&rsquo;s see a rather didactic example of a cache group:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">cacheGroupFoo<\/span><span style=\"color:#f92672\">:<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>\t<span style=\"color:#75715e\">\/\/ The number of chunks the module must appear in\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>\t<span style=\"color:#a6e22e\">minChunks<\/span>: <span style=\"color:#66d9ef\">3<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>   \t<span style=\"color:#75715e\">\/\/ Number of bytes put in a chunk(i.e. the sum of the number of bytes for each constituent module)\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>\t<span style=\"color:#75715e\">\/\/ For example, if a chunk contains 2 modules, `x` and `w`, then `nrBytesChunk = nrBytes(x) + nrBytes(w)`.\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>\t<span style=\"color:#a6e22e\">minSize<\/span>: <span style=\"color:#66d9ef\">10<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>\t<span style=\"color:#75715e\">\/\/ Which modules are to be considered\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>\t<span style=\"color:#a6e22e\">modulePathPattern<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">\/node_modules\/<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p>Based on what we&rsquo;ve seen above, a new chunk will be created if all these conditions are met simultaneously:<\/p>\n<ul>\n<li>the module must belong to at least 3 chunks<\/li>\n<li>the minimum number of bytes of a chunk must be at least 10<\/li>\n<li>the modules that would lead to new chunks being created must come from the <code>node_modules<\/code> folder<\/li>\n<\/ul>\n<p>So, this is what a <strong>cache group<\/strong> looks like. From such cache groups there can be many chunks created. If, for example, the <code>x<\/code> module is required in 3 different chunks, it belongs to the <code>node_modules<\/code> folder and it has at least 10 bytes(the chunk that would be created would also have 10 bytes), then, based on the above cache group, <code>x<\/code> will be extracted into its own chunk. If there is another module from <code>node_modules<\/code>, <code>w<\/code>, which is required in 4 different chunks, then there will be <strong>another chunk for the <code>w<\/code> module,<\/strong> assuming all the other conditions described by the above cache group are fulfilled. If <code>w<\/code> was required in only 3 chunks, then it would be put in the same chunk as <code>x<\/code>. A StackBlitz app that covers this situation can be found <a href=\"https:\/\/stackblitz.com\/edit\/node-gfzz8i?file=src%2Findex.js\" target=\"_blank\" rel=\"noopener\">here<\/a>(make sure to follow the instructions listed in the <code>readme<\/code> file).<\/p>\n<p>If <code>SplitChunksPlugin<\/code> \u00a0is used with the <strong>default options<\/strong>,<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/* ... *\/<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">optimization<\/span><span style=\"color:#f92672\">:<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#75715e\">\/\/ splitChunks: false,\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>  <span style=\"color:#a6e22e\">splitChunks<\/span><span style=\"color:#f92672\">:<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">minSize<\/span>: <span style=\"color:#66d9ef\">0<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  },\n<\/span><\/span><span style=\"display:flex;\"><span>},\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/* ... *\/<\/span>\n<\/span><\/span><\/code><\/pre><\/div><p>or more specifically, without explicitly mentioning the cache groups, the plugin will use <strong><a href=\"https:\/\/github.com\/webpack\/webpack\/blob\/v5.65.0\/lib\/config\/defaults.js#L1101-L1112\" target=\"_blank\" rel=\"noopener\">2 implicit cache groups<\/a>,<\/strong> which would be the same as if we explicitly declared them as follows:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/* ... *\/<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">optimization<\/span><span style=\"color:#f92672\">:<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">splitChunks<\/span><span style=\"color:#f92672\">:<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>  \t<span style=\"color:#66d9ef\">default<\/span><span style=\"color:#f92672\">:<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#a6e22e\">idHint<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#34;&#34;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#a6e22e\">reuseExistingChunk<\/span>: <span style=\"color:#66d9ef\">true<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#a6e22e\">minChunks<\/span>: <span style=\"color:#66d9ef\">2<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#a6e22e\">priority<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#f92672\">-<\/span><span style=\"color:#ae81ff\">20<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>    },\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">defaultVendors<\/span><span style=\"color:#f92672\">:<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#a6e22e\">idHint<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#34;vendors&#34;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#a6e22e\">reuseExistingChunk<\/span>: <span style=\"color:#66d9ef\">true<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#a6e22e\">test<\/span>: <span style=\"color:#66d9ef\">NODE_MODULES_REGEXP<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#a6e22e\">priority<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#f92672\">-<\/span><span style=\"color:#ae81ff\">10<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>    }\n<\/span><\/span><span style=\"display:flex;\"><span>  },\n<\/span><\/span><span style=\"display:flex;\"><span>},\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/* ... *\/<\/span>\n<\/span><\/span><\/code><\/pre><\/div><p>Don&rsquo;t worry about the new options, some of them will be covered later in the article. For now, it&rsquo;s enough to understand what&rsquo;s going on at a high level.<\/p>\n<p>There are 2 cache groups - the <code>default<\/code> one, which <strong>targets any module<\/strong> from our application(i.e. doesn&rsquo;t matter where it comes from); there is then the <code>defaultVendors<\/code> group which <strong>only<\/strong> targets the modules which come from <code>node_modules<\/code>(the <code>test<\/code> property implies that). As you probably noticed, the latter cache group has a greater priority and this plays an important role when a module <strong>belongs to<\/strong> <strong>multiple cache groups<\/strong>. Since we already know that a cache group is what <em>produces<\/em> new chunks, then a module would belong to multiple new chunks, which is <strong>not desirable<\/strong> because we would arrive to the same problem that we are trying to solve: code duplication. So, the <code>priority<\/code> option will help determine which <strong>unique chunk<\/strong> the module will belong to, while the other alternatives which the module could be part of are discarded.<\/p>\n<p>In order to make these defaults cache groups a bit clearer, let&rsquo;s see the chunks they create in an example we&rsquo;ve seen in a previous section, namely the one where <code>SplitChunksPlugin<\/code> was introduced. <a href=\"https:\/\/stackblitz.com\/edit\/node-tlym1w?file=readme.md\" target=\"_blank\" rel=\"noopener\">Here<\/a> is the link to its corresponding StackBlitz app.<\/p>\n<p>The webpack configuration file looks like this:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span>{\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">mode<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;production&#39;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">entry<\/span><span style=\"color:#f92672\">:<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">main<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;.\/src&#39;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  },\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">output<\/span><span style=\"color:#f92672\">:<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">path<\/span>: <span style=\"color:#66d9ef\">path.join<\/span>(<span style=\"color:#a6e22e\">__dirname<\/span>, <span style=\"color:#e6db74\">&#39;dist&#39;<\/span>),\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">filename<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;[name].js&#39;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">clean<\/span>: <span style=\"color:#66d9ef\">true<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  },\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">optimization<\/span><span style=\"color:#f92672\">:<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#75715e\">\/\/ Instruct webpack not to obfuscate the resulting code\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>    <span style=\"color:#a6e22e\">minimize<\/span>: <span style=\"color:#66d9ef\">false<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">splitChunks<\/span><span style=\"color:#f92672\">:<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#a6e22e\">minSize<\/span>: <span style=\"color:#66d9ef\">0<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>    },\n<\/span><\/span><span style=\"display:flex;\"><span>  },\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">context<\/span>: <span style=\"color:#66d9ef\">__dirname<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>};\n<\/span><\/span><\/code><\/pre><\/div><blockquote>\n<p>A cache group inherits some options if they are not specified in the cache group itself. For example, <code>minSize: 0<\/code> will be inherited by both <code>default<\/code> and <code>defaultVendors<\/code> cache groups(the default cache groups). You can see the options a cache group can inherit <a href=\"https:\/\/github.com\/webpack\/webpack\/blob\/main\/types.d.ts#L7814\" target=\"_blank\" rel=\"noopener\">here<\/a>, in wepback&rsquo;s types declaration file.<\/p>\n<\/blockquote>\n<p>After running <code>npm run build<\/code>, let&rsquo;s explore the output in the <code>dist<\/code> directory. In addition to the files we are already familiar with, namely the <code>main<\/code> and the <code>async-*<\/code> files(each file being associated with its chunk), new files appeared:<\/p>\n<p><p class=\"markdown-image\">\n  <img src=\"images\/file-struct-understanding-defaults.png\" alt=\"file-struct-understanding-defaults.png\"  \/>\n<\/p><\/p>\n<blockquote>\n<p>Although the generated files might have different names, their content won&rsquo;t be different from what we will see next.<\/p>\n<\/blockquote>\n<p>Of course, since a file from <code>dist<\/code> defines its own chunk, these new files indicate the presence of new chunks.<\/p>\n<p>It&rsquo;s no doubt that these new chunks were created by <code>SplitChunksPlugin<\/code>, but the question now is <em>what modules are inside these chunks?<\/em> Before inspecting what&rsquo;s inside the files, here is the diagram which depicts the file structure and the chunks created by default(without the <code>SplitChunksPlugin<\/code>&rsquo;s involvement):<\/p>\n<p><p class=\"markdown-image\">\n  <img src=\"images\/file-structure-1.png\" alt=\"file-structure.png\"  \/>\n<\/p><\/p>\n<p><em>A link for the above diagram can be found <a href=\"https:\/\/excalidraw.com\/#json=VDeCLP274PUk7GR8KS8N0,epOXJ2Y-EPPOXQzirAnXfQ\" target=\"_blank\" rel=\"noopener\">here<\/a>.<\/em><\/p>\n<p>We will use this diagram to understand why each new chunk has been created, so we will be referring to it often. Let&rsquo;s start now going through each new file, starting from topmost file.<\/p>\n<p>Here, once again, are the default cache groups, we will need them to understand why some modules are part of a certain chunk:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ The default cache groups that `SplitChunksPlugin` uses.\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span><span style=\"color:#66d9ef\">default<\/span><span style=\"color:#f92672\">:<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">idHint<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#34;&#34;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">reuseExistingChunk<\/span>: <span style=\"color:#66d9ef\">true<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">minChunks<\/span>: <span style=\"color:#66d9ef\">2<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">priority<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#f92672\">-<\/span><span style=\"color:#ae81ff\">20<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>},\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">defaultVendors<\/span><span style=\"color:#f92672\">:<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">idHint<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#34;vendors&#34;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">reuseExistingChunk<\/span>: <span style=\"color:#66d9ef\">true<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">test<\/span>: <span style=\"color:#66d9ef\">NODE_MODULES_REGEXP<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">priority<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#f92672\">-<\/span><span style=\"color:#ae81ff\">10<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p>For <code>571.js<\/code> we have:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/* ... *\/<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">__WEBPACK_DEFAULT_EXPORT__<\/span> <span style=\"color:#f92672\">=<\/span> (<span style=\"color:#e6db74\">&#39;z&#39;<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/* ... *\/<\/span>\n<\/span><\/span><\/code><\/pre><\/div><p>so here we have the <code>z<\/code> module. Why is that, though? Well, <code>z<\/code> belongs to the <code>node_modules<\/code> folder(as observed from the above screenshot) and thus the targeted <strong>chunk group<\/strong> is <code>defaultVendors<\/code> which <strong>doesn&rsquo;t impose any constraints<\/strong> on the number of chunks the module must appear in. In this case, <code>z<\/code> belongs only to the <code>async-c<\/code> chunk and this is acceptable for <code>defaultVendors<\/code>. It is true that <code>z<\/code> could belong to the other cache group, <code>default<\/code>, but <code>defaultVendors<\/code> has a greater priority, so <code>z<\/code> will belong to the latter.<\/p>\n<p>For <code>616.js<\/code>:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/* ... *\/<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">__WEBPACK_DEFAULT_EXPORT__<\/span> <span style=\"color:#f92672\">=<\/span> (<span style=\"color:#e6db74\">&#39;y&#39;<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/* ... *\/<\/span>\n<\/span><\/span><\/code><\/pre><\/div><p>this is the <code>y<\/code> module. It gets placed in a different chunk because it is belongs to the <code>node_modules<\/code> folder(so <code>defaultVendors<\/code> is once more accountable for the newly created chunk) and it appears in the <code>async-b<\/code> and <code>async-a<\/code> chunks.<\/p>\n<p>For <code>673.js<\/code>:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/* ... *\/<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">__WEBPACK_DEFAULT_EXPORT__<\/span> <span style=\"color:#f92672\">=<\/span> (<span style=\"color:#e6db74\">&#39;d&#39;<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/* ... *\/<\/span>\n<\/span><\/span><\/code><\/pre><\/div><p>this is the <code>d<\/code> module. As seen from the screenshot, it does not comes from <code>node_modules<\/code>. It means the <code>default<\/code> cache group is responsible for creating this chunk. If we take closer look at the diagram, we will see that it is requested from <code>async-a<\/code>, <code>async-b<\/code>, <code>async-c<\/code> chunks. This means 3 chunks, and the <code>default<\/code> cache groups says that the minimum number of chunks a module must appear in should be at least 2. This condition is met, so that&rsquo;s why this module is put into a separate chunk.<\/p>\n<p>For <code>714.js<\/code>:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/* ... *\/<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">__WEBPACK_DEFAULT_EXPORT__<\/span> <span style=\"color:#f92672\">=<\/span> (<span style=\"color:#e6db74\">&#39;f&#39;<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/* ... *\/<\/span>\n<\/span><\/span><\/code><\/pre><\/div><p>this is the <code>f<\/code> module. As can be noticed from the diagram, <code>f<\/code> belong to 3 chunks: <code>async-g<\/code>, <code>async-b<\/code> and <code>async-c<\/code>. Judging by the screenshot, the <code>f<\/code> module does not comes from <code>node_modules<\/code>, so it&rsquo;s the same case as above, meaning that this chunk has been created due to the <code>default<\/code> cache group.<\/p>\n<p>And finally, for <code>934.js<\/code>:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/* ... *\/<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">__WEBPACK_DEFAULT_EXPORT__<\/span> <span style=\"color:#f92672\">=<\/span> (<span style=\"color:#e6db74\">&#39;some content from `x.js`!&#39;<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/* ... *\/<\/span>\n<\/span><\/span><\/code><\/pre><\/div><p>as expected, this is the <code>x<\/code> module. You might have guess it why it gets placed in a new chunk, since we&rsquo;ve talked about it a few times throughout the article: it&rsquo;s from <code>node_modules<\/code>(so <code>defaultVendors<\/code> created this new chunk). Additionally, it is requested from 3 chunks, but this would matter only if we explicitly used the <code>minChunks<\/code> option in the <code>defaultVendors<\/code> cache group.<\/p>\n<p>So, these are effects of using the default options of <code>SplitChunksPlugin<\/code>. By the way, if you are interested to see how <strong>cache groups<\/strong> are compared in order to determine which one should be used to create new chunks, <a href=\"https:\/\/github.com\/webpack\/webpack\/blob\/v5.65.0\/lib\/optimize\/SplitChunksPlugin.js#L231-L255\" target=\"_blank\" rel=\"noopener\">here&rsquo;s the source code<\/a> that does that.<\/p>\n<p>It was necessary to spend some time on comprehending how the default cache groups work, otherwise it would be though and challenging to <em>control<\/em> them in order to help <code>SplitChunksPlugin<\/code> achieve the results we are looking for. This also serves as a base for investigating some of the <code>SplitChunksPlugin<\/code>&rsquo;s options that we have at our disposal.<\/p>\n<p>But before we do that, let&rsquo;s quickly see how we can disable a cache group, since we will apply this idea in the following sections, in order to make things a bit easier to grasp. To illustrate, we will disable the <code>default<\/code> cache group.<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/* ... *\/<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">optimization<\/span><span style=\"color:#f92672\">:<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">splitChunks<\/span><span style=\"color:#f92672\">:<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#a6e22e\">cacheGroups<\/span><span style=\"color:#f92672\">:<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>        \t<span style=\"color:#75715e\">\/\/ We&#39;re disabling it by setting it to false.\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>        \t<span style=\"color:#66d9ef\">default<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#66d9ef\">false<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>        },\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#a6e22e\">minSize<\/span>: <span style=\"color:#66d9ef\">0<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  },\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/* ... *\/<\/span>\n<\/span><\/span><\/code><\/pre><\/div><p><em>You can run this project which includes the above configuration <a href=\"https:\/\/stackblitz.com\/edit\/node-wy87gh?file=readme.md\" target=\"_blank\" rel=\"noopener\">in this StackBlitz app<\/a>.<\/em><\/p>\n<p>If we were now to run <code>npm run build<\/code>, what would you expected the newly generated chunks to be? Well, if the <code>default<\/code> cache group is disabled, then only modules from <code>node_modules<\/code> are taken into account. And since there are no other constraints, apart from <code>minSize<\/code>(without it we wouldn&rsquo;t be seeing any newly generated chunks since the files are too small compared to the <code>minSize<\/code>&rsquo;s default value), then, based on what we&rsquo;ve learned in this section, the <code>dist<\/code> directory should contain 3 newly generated chunks, one for each of the <code>x<\/code>, <code>y<\/code> and <code>z<\/code> modules:<\/p>\n<p><p class=\"markdown-image\">\n  <img src=\"images\/disabling-default-cache-group.png\" alt=\"disabling-default-cache-group.png\"  \/>\n<\/p><\/p>\n<p>In the upcoming sections, we will explore some of the <code>SplitChunksPlugin<\/code>&rsquo;s capabilities. For the sake of simplifying things, each example that we&rsquo;ll see will have one of the default cache groups disabled, so that we can focus on what that example is trying to emphasize. Let&rsquo;s get into it!<\/p>\n<h2 id=\"the-minchunks-option\">\n  <span>\n  The <code>minChunks<\/code> option\n  <\/span>\n  <a href=\"#the-minchunks-option\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><p>We have already encountered this property through the article: it indicates the minimum number of chunks that must require a module. Let&rsquo;s recall that in order for new chunks to be created by <code>SplitChunksPlugin<\/code>, they must fulfil a <em>collection of requirements.<\/em> That is to say, the chunk must belong to a certain <strong>cache group<\/strong>.<\/p>\n<p>To make things a bit easier to understand, let&rsquo;s take an example where we want these conditions to be met:<\/p>\n<ul>\n<li>the module that the new chunks will contain must come from <code>node_modules<\/code><\/li>\n<li>the module must appear in at least 3 chunks<\/li>\n<\/ul>\n<p>With these restrictions in mind, this is how the webpack configuration would look like:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">optimization<\/span><span style=\"color:#f92672\">:<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#75715e\">\/\/ Instruct webpack not to obfuscate the resulting code\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>    <span style=\"color:#a6e22e\">minimize<\/span>: <span style=\"color:#66d9ef\">false<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">splitChunks<\/span><span style=\"color:#f92672\">:<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#75715e\">\/\/ minSize: 0,\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>      <span style=\"color:#75715e\">\/\/ minChunks: 3,\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>      <span style=\"color:#a6e22e\">cacheGroups<\/span><span style=\"color:#f92672\">:<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#75715e\">\/\/ Disabling this group so that we can focus on one thing at a time.\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>        <span style=\"color:#66d9ef\">default<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#66d9ef\">false<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#a6e22e\">defaultVendors<\/span><span style=\"color:#f92672\">:<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>          <span style=\"color:#75715e\">\/\/ We could have also set this property as: `splitChunks.minSize: 0`,\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>          <span style=\"color:#75715e\">\/\/ since this property is inherited(by default) by the cache groups.\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>          <span style=\"color:#a6e22e\">minSize<\/span>: <span style=\"color:#66d9ef\">0<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>          <span style=\"color:#75715e\">\/\/ Enforcing the minimum number of chunks that request a module.\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>          <span style=\"color:#a6e22e\">minChunks<\/span>: <span style=\"color:#66d9ef\">3<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>          <span style=\"color:#75715e\">\/\/ Q: What kind of modules should new chunks contain?\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>          <span style=\"color:#75715e\">\/\/ A: Modules that come from `node_modules`\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>          <span style=\"color:#a6e22e\">test<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">\/node_modules\/<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>        },\n<\/span><\/span><span style=\"display:flex;\"><span>      },\n<\/span><\/span><span style=\"display:flex;\"><span>    },\n<\/span><\/span><span style=\"display:flex;\"><span>  },\n<\/span><\/span><\/code><\/pre><\/div><p><em>A StackBlitz demo that exemplifies this option can be found <a href=\"https:\/\/stackblitz.com\/edit\/node-eviijf?file=readme.md\" target=\"_blank\" rel=\"noopener\">here<\/a>.<\/em><\/p>\n<p>What would be the contents of <code>dist<\/code> after running <code>npm run build<\/code> ? Apart from the chunks we&rsquo;re already familiar with(<code>main<\/code> and <code>async-*<\/code>), there is only a new chunk and it contains the <code>x<\/code> module. Based on the first diagram that we saw earlier(whose link can be found <a href=\"https:\/\/excalidraw.com\/#json=VDeCLP274PUk7GR8KS8N0,epOXJ2Y-EPPOXQzirAnXfQ\" target=\"_blank\" rel=\"noopener\">here<\/a>), this is the only module that comes from <code>node_modules<\/code> and is present in at least 3 chunks:<\/p>\n<p><p class=\"markdown-image\">\n  <img src=\"images\/min-chunks-answer.png\" alt=\"min-chunks-answer.png\"  \/>\n<\/p><\/p>\n<p>What would be the output if we set <code>minChunks: 2<\/code>? Since this change basically says that the minimum number of chunks should now be <code>2<\/code> instead of <code>3<\/code>, then we should see 2 chunks: one which contains the <code>x<\/code> module and one which contains the <code>y<\/code> module. Feel free to try that in the StackBlitz app!<\/p>\n<h2 id=\"the-chunks-option\">\n  <span>\n  The <code>chunks<\/code> option\n  <\/span>\n  <a href=\"#the-chunks-option\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><p>We&rsquo;ve heard a few times phrases like <em>module <code>x<\/code> appears in <code>N<\/code> different chunks.<\/em> With the help of the <code>chunks<\/code> option we can specify the <em>types<\/em> of those chunks. We didn&rsquo;t talk much about <em>chunks<\/em> and other adjacent concepts until this point, so we will review some of these ideas now. For this reason, we will have to check the initial diagram again:<\/p>\n<p><p class=\"markdown-image\">\n  <img src=\"images\/file-structure-2.png\" alt=\"file-structure.png\"  \/>\n<\/p><\/p>\n<p><em>A link for the above diagram can be found <a href=\"https:\/\/excalidraw.com\/#json=VDeCLP274PUk7GR8KS8N0,epOXJ2Y-EPPOXQzirAnXfQ\" target=\"_blank\" rel=\"noopener\">here<\/a>.<\/em><\/p>\n<p>Apart from the fact that a chunk contains more modules, the concept of a <em>chunk<\/em> could be hard to picture. With these bits of information that we have, we can deduce <strong>2 types of chunks<\/strong> from the diagram(the chunks are framed in green):<\/p>\n<ul>\n<li>the <strong>async chunks<\/strong>: it&rsquo;s about the <code>async-*<\/code> chunks; <em>what do these chunks have in common?<\/em> - they are all created as a result of using the <code>import()<\/code> function<\/li>\n<li>the <strong>initial\/main chunks<\/strong>: only one chunk from the above diagram fits into this category - the <code>main<\/code> chunk; <em>what exactly is a main chunk? -<\/em> it, like any other types of chunks, contains modules that are to be rendered and used in the application, but this kind of chunk also contains a lot of so-called <strong>runtime code<\/strong>; this is the code that <em>ties together<\/em> all the generated chunks so that our application can work properly; for example, the runtime code contains the logic for loading the <strong>async chunks<\/strong> and integrate them within the application; usually, this kind of chunks(initial chunks) can be recognised when defining items in the <code>entry<\/code> object(e.g. <code>{ entry: { main: '.\/index.js' } }<\/code>)<\/li>\n<\/ul>\n<p>Now coming back to the <code>chunks<\/code> option, it accepts 4 values:<\/p>\n<ul>\n<li><code>async<\/code> - <strong>only<\/strong> the <strong>async chunks<\/strong> will be taken into account by the cache group in question(this is the default behaviour); so, not only can we specify the number of chunks a module must be part of, but also the chunk\u2019s type<\/li>\n<li><code>initial<\/code> - <strong>only<\/strong> the <strong>initial\/main<\/strong> chunks are taken into account<\/li>\n<li><code>all<\/code> - any chunk<\/li>\n<li>a predicate function that will determine which chunk will be considered; here we can filter out chunks by using many of the chunk&rsquo;s properties: its name, its constituent modules etc.<\/li>\n<\/ul>\n<p>It is worthwhile to underline the <strong>connection<\/strong> between the <code>chunks<\/code> option and <code>minChunks<\/code>. We use the <code>chunks<\/code> option in order to filter out certain chunks and then <code>SplitChunksPlugin<\/code> <a href=\"https:\/\/github.com\/webpack\/webpack\/blob\/v5.65.0\/lib\/optimize\/SplitChunksPlugin.js#L1068-L1069\" target=\"_blank\" rel=\"noopener\">checks the number of remaining chunks against <code>minChunks<\/code><\/a>. To give an example, <a href=\"https:\/\/stackblitz.com\/edit\/node-3kmfgr?file=readme.md\" target=\"_blank\" rel=\"noopener\">here&rsquo;s a StackBlitz project<\/a> which has the following structure:<\/p>\n<p><p class=\"markdown-image\">\n  <img src=\"images\/chunks-option-a-initial.png\" alt=\"Content image\"  \/>\n<\/p><\/p>\n<p><em>A link for the above diagram can be found <a href=\"https:\/\/excalidraw.com\/#json=umfHzfM2ndo2LlxI2S41D,FpXjw_T0kELja0TwEKCJmQ\" target=\"_blank\" rel=\"noopener\">here<\/a>.<\/em><\/p>\n<p>As noticed from the diagram, we have a new <strong>main chunk:<\/strong> <code>a-initial<\/code>. This chunk corresponds to the <code>a-initial<\/code> item in the <strong>entry object<\/strong> from the configuration file. As a result, the <code>x<\/code> module will be request from one more chunk.<\/p>\n<p>Let&rsquo;s try to solve this problem: we want new chunks to be created <strong>only if<\/strong> their constituent modules are required in at least 4 other chunks, regardless of whether the chunk is async or not(basically we&rsquo;re considering all chunks). Here&rsquo;s a way to configure <code>SplitChunksPlugin<\/code> so that we can achieve the desired result:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">optimization<\/span><span style=\"color:#f92672\">:<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#75715e\">\/\/ Instruct webpack not to obfuscate the resulting code\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>  <span style=\"color:#a6e22e\">minimize<\/span>: <span style=\"color:#66d9ef\">false<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">splitChunks<\/span><span style=\"color:#f92672\">:<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">minSize<\/span>: <span style=\"color:#66d9ef\">0<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">chunks<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;all&#39;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">minChunks<\/span>: <span style=\"color:#66d9ef\">4<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">cacheGroups<\/span><span style=\"color:#f92672\">:<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#75715e\">\/\/ Disabling this cache group.\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>      <span style=\"color:#66d9ef\">default<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#66d9ef\">false<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>    },\n<\/span><\/span><span style=\"display:flex;\"><span>  },\n<\/span><\/span><span style=\"display:flex;\"><span>},\n<\/span><\/span><\/code><\/pre><\/div><p>Notice that with <code>chunks: 'all'<\/code> we are essentially saying this to <code>SplitChunksPlugin<\/code>: <em>please consider any chunk that requires a module, doesn&rsquo;t matter whether it&rsquo;s async or initial or of any other type.<\/em><\/p>\n<p>Once <code>npm run build<\/code> is invoked, we should see only one new chunk generated which unsurprisingly contains only the module <code>x<\/code>:<\/p>\n<p><p class=\"markdown-image\">\n  <img src=\"images\/chunks-option-ss.png\" alt=\"chunks-option-ss.png\"  \/>\n<\/p><\/p>\n<p>We will end this section with a few small tasks that aim to clarify this option even more.<\/p>\n<blockquote>\n<p>What follows is based on the above diagram that depicts the chunks and their modules. It is recommended to try out the following configurations in the StackBlitz app that has been provided earlier.<\/p>\n<\/blockquote>\n<p>Do you find anything <em>wrong<\/em> with the below configuration? (aiming at the <code>chunk<\/code> and <code>minChunks<\/code> duo)<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">optimization<\/span><span style=\"color:#f92672\">:<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">minimize<\/span>: <span style=\"color:#66d9ef\">false<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">splitChunks<\/span><span style=\"color:#f92672\">:<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">minSize<\/span>: <span style=\"color:#66d9ef\">0<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">chunks<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;async&#39;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">minChunks<\/span>: <span style=\"color:#66d9ef\">4<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">cacheGroups<\/span><span style=\"color:#f92672\">:<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#75715e\">\/\/ Disabling this cache group.\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>      <span style=\"color:#66d9ef\">default<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#66d9ef\">false<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>    },\n<\/span><\/span><span style=\"display:flex;\"><span>  },\n<\/span><\/span><span style=\"display:flex;\"><span>},\n<\/span><\/span><\/code><\/pre><\/div><p>The problem is that there is no module that appears in 4 <strong>async chunks<\/strong> - so we will end up only with duplicated code, since no separate chunks have been created! The closest it gets to is 3 and we&rsquo;re talking about the <code>x<\/code> module here. In order to properly extract the <code>x<\/code>&rsquo;s code into a new chunk, we will have to change <code>minChunks: 4<\/code> to <code>minChunks: 3<\/code>(feel free to try this out in the StackBlitz project).<\/p>\n<p>What about the next configuration? What are we asking webpack to do here?<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">optimization<\/span><span style=\"color:#f92672\">:<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">minimize<\/span>: <span style=\"color:#66d9ef\">false<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">splitChunks<\/span><span style=\"color:#f92672\">:<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">minSize<\/span>: <span style=\"color:#66d9ef\">0<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">chunks<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;initial&#39;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">minChunks<\/span>: <span style=\"color:#66d9ef\">4<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">cacheGroups<\/span><span style=\"color:#f92672\">:<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#75715e\">\/\/ Disabling this cache group.\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>      <span style=\"color:#66d9ef\">default<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#66d9ef\">false<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>    },\n<\/span><\/span><span style=\"display:flex;\"><span>  },\n<\/span><\/span><span style=\"display:flex;\"><span>},\n<\/span><\/span><\/code><\/pre><\/div><p>We&rsquo;re telling webpack to split chunks(i.e. create new chunks) only if they contain modules which come <code>node_modules<\/code>(hence the <code>defaultVendors<\/code> group) and which appear in at least 4 <strong>initial<\/strong> chunks. In our case, there is only one initial chunk that requires such modules: the <code>a-initial<\/code> chunk which requires the modules <code>x<\/code> and <code>z<\/code>(there is also the <code>main<\/code> chunk, but it only requires modules via the <code>import()<\/code> function). So, the correction here would be to change <code>minChunks: 4<\/code> to <code>minChunks: 1<\/code>.<\/p>\n<p>In this section there were a bunch of new concepts we&rsquo;ve learned about and the beautiful thing about it is that they will be of use in the following articles, where we will explore other configuration options for this plugin.<\/p>\n<h2 id=\"conclusion\">\n  <span>\n  Conclusion\n  <\/span>\n  <a href=\"#conclusion\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><p>Although this learning journey probably turned out to be not so easy, I hope the effort was worth it.<\/p>\n<p>To <strong>quickly recap<\/strong> one of the problem this plugin solves: <strong>code duplication<\/strong> - a module is copied in multiple <strong>chunks<\/strong> and this sometimes can be expensive, especially when the module is at least a few hundreds lines of code. A solution to this problem is <em>centralise<\/em> these kinds of modules, so that they can be reused by multiple consumers. This can be achieved by placing the module in question in a separate chunk which will be loaded(fetched over the network as an HTTP request) only once.<br>\nNow a question arises: <em>what are the criteria based on which these separate chunks are created? -<\/em> here is where <code>SplitChunksPlugin<\/code> comes into play - it decides on how to properly organise into chunks the modules which are very frequently used in multiple places.<\/p>\n<p><strong>Thanks for reading!<\/strong><\/p>\n<p><em>The diagrams have been made with <a href=\"https:\/\/excalidraw.com\/\" target=\"_blank\" rel=\"noopener\">Excalidraw<\/a>.<\/em><\/p>\n<p><em>Special thanks <a href=\"https:\/\/twitter.com\/maxkoretskyi\" target=\"_blank\" rel=\"noopener\">Max Koretskyi<\/a> for reviewing this article and for providing extremely valuable feedback.<\/em><\/p>\n"},{"title":"Demystifying webpack's 'import' function: using dynamic arguments","link":"https:\/\/andreigatej.dev\/blog\/webpack-import-function-dynamic-arguments\/","pubDate":"Thu, 28 Oct 2021 00:00:00 +0000","guid":"https:\/\/andreigatej.dev\/blog\/webpack-import-function-dynamic-arguments\/","description":"<h2 id=\"introduction\">\n  <span>\n  Introduction\n  <\/span>\n  <a href=\"#introduction\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><p>Although it is a popular selling point of webpack, the <code>import<\/code> function has many hidden details and features that many developers may not be aware of. For instance, the <code>import<\/code> function can accept dynamic expression and still be able to achieve well known features such as lazy loading. You can think of a dynamic expression as anything that&rsquo;s not a <strong>raw string<\/strong>(e.g <code>import('.\/path\/to\/file.js')<\/code>). A few examples of dynamic expressions could be: <code>import('.\/animals\/' + 'cat' + '.js')<\/code>, <code>import('.\/animals\/' + animalName + '.js')<\/code>, where <code>animalName<\/code> could be known at runtime or compile time. In this article, we will dive deep into the concept of dynamic expressions when it comes to the <code>import<\/code> function and hopefully, at the end, you will be more acquainted with the range of possibilities that this webpack&rsquo;s feature provides.<\/p>\n<p>There are no special prerequisites, apart from a basic understanding of how the <code>import<\/code> function behaves when its argument is static(i.e it creates a new chunk). There is also an article named <em><a href=\"https:\/\/andreigatej.dev\/blog\/webpack-bundling-process\/\">An in-depth perspective on webpack&rsquo;s bundling process<\/a><\/em> in which concepts such as <code>Module<\/code>s and <code>Chunk<\/code>s are explained, but it shouldn&rsquo;t affect the understanding of this article too much.<\/p>\n<p>Throughout the article we will be using live examples(all of them in the form of a StackBlitz app) and diagrams, so let&rsquo;s get started!<\/p>\n<h2 id=\"the-implications-of-dynamic-arguments\">\n  <span>\n  The implications of dynamic arguments\n  <\/span>\n  <a href=\"#the-implications-of-dynamic-arguments\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><p>Although the value is not known at compile time, by using the <code>import()<\/code> function with dynamic arguments we can <strong>still achieve lazy loading<\/strong>. Unlike SystemJS, webpack can&rsquo;t load any arbitrary module at runtime, so the fact that the value will be known at runtime will constrain webpack to make sure that <strong>all the possible values<\/strong> that the argument can resolve to are accounted for. We will see what is meant by that in the following sections, where we will examine the customizations the <code>import<\/code> function can accept.<\/p>\n<p>For now, we will focus on the <code>import<\/code>&rsquo;s argument. All the following sections will be based on the same example where there is a directory called <code>animals<\/code> \u00a0and inside there are files that correspond to animals:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-markdown\" data-lang=\"markdown\"><span style=\"display:flex;\"><span>\u251c\u2500\u2500 animals\n<\/span><\/span><span style=\"display:flex;\"><span>\u2502   \u251c\u2500\u2500 cat.js\n<\/span><\/span><span style=\"display:flex;\"><span>\u2502   \u251c\u2500\u2500 dog.js\n<\/span><\/span><span style=\"display:flex;\"><span>\u2502   \u251c\u2500\u2500 fish.js\n<\/span><\/span><span style=\"display:flex;\"><span>\u2502   \u2514\u2500\u2500 lion.js\n<\/span><\/span><span style=\"display:flex;\"><span>\u251c\u2500\u2500 index.js\n<\/span><\/span><\/code><\/pre><\/div><p>Each examples uses the <code>import<\/code> function like this: <code>import('.\/animals\/${fileName}.js')<\/code>. As far as the <code>.\/animals\/${fileName}.js<\/code> segment is concerned, each <code>${fileName}<\/code> refers to a <strong>dynamic part<\/strong> and it will be replaced with <code>\/.*\/<\/code> by default(you can think of it as a glob pattern). The given expression can have multiple dynamic parts. The provided argument will eventually result into a RegExp object which will be used to determine which files should be considered later. The traversal starts from the first <strong>static<\/strong> part of the provided path(in this case it is <code>.\/animals<\/code>) and in each step it will read the files from the current directory and will test the RegExp object against them. It can also traverse nested directories(this is the default behaviour) and once the files are properly discovered, webpack will proceed based on the chosen mode. In this example, <strong>the resulting RegExp<\/strong> object will be <code>\/^\\\\.\\\\\/.*\\\\.js$\/<\/code> and it will be tested against all the files which reside in the <code>animals\/<\/code> directory(e.g <code>regExp.test('.\/cat.js')<\/code>).<\/p>\n<p>It&rsquo;s important to mention that the traversal and the file discovery are done <strong>at compile time.<\/strong><\/p>\n<p>As a side note, the replacement for the dynamic parts and whether nested directories should be traversed can be chosen by us in the config file:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ wepback.config.js\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span><span style=\"color:#a6e22e\">module<\/span><span style=\"color:#f92672\">:<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">parser<\/span><span style=\"color:#f92672\">:<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#a6e22e\">javascript<\/span><span style=\"color:#f92672\">:<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#a6e22e\">wrappedContextRegExp<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">\/.*\/<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>\t\t\t\t<span style=\"color:#a6e22e\">wrappedContextRecursive<\/span>: <span style=\"color:#66d9ef\">true<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>      }\n<\/span><\/span><span style=\"display:flex;\"><span>    }\n<\/span><\/span><span style=\"display:flex;\"><span>  }\n<\/span><\/span><\/code><\/pre><\/div><p>So, <code>wrappedContextRecursive<\/code> specifies whether nested directories should be traversed or not(e.g \u00a0considering files inside <code>animals\/aquatic\/<\/code> too or not) and with <code>wrappedContextRegExp<\/code> we can tell webpack what to replace the expression&rsquo;s dynamic parts with.<\/p>\n<p>Based on the default configuration, our initial expression <code>.\/animals\/${fileName}.js<\/code> will result in <code>.\/animals\/.*.js<\/code>(loosely).<br>\nIn the upcoming sections we will explore what happens once these files have been figured.<\/p>\n<p>Let&rsquo;s get into it!<\/p>\n<h2 id=\"the-lazy-mode\">\n  <span>\n  The <code>lazy<\/code> mode\n  <\/span>\n  <a href=\"#the-lazy-mode\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><p><em>The example this section is based on can be found <a href=\"https:\/\/stackblitz.com\/edit\/node-eujyms?file=readme.md\" target=\"_blank\" rel=\"noopener\">here<\/a>(make sure to also start the server).<\/em><\/p>\n<p>This is the default mode, meaning that you don&rsquo;t have to explicitly specify it. Suppose there is a directory structure that looks like this:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-markdown\" data-lang=\"markdown\"><span style=\"display:flex;\"><span>\u251c\u2500\u2500 animals\n<\/span><\/span><span style=\"display:flex;\"><span>\u2502   \u251c\u2500\u2500 cat.js\n<\/span><\/span><span style=\"display:flex;\"><span>\u2502   \u251c\u2500\u2500 dog.js\n<\/span><\/span><span style=\"display:flex;\"><span>\u2502   \u251c\u2500\u2500 fish.js\n<\/span><\/span><span style=\"display:flex;\"><span>\u2502   \u2514\u2500\u2500 lion.js\n<\/span><\/span><span style=\"display:flex;\"><span>\u2514\u2500\u2500 index.js\n<\/span><\/span><\/code><\/pre><\/div><p>By using the <code>import<\/code> function in our application code:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ index.js\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ In this example, the page shows an `input` tag and a button.\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ The user is supposed to type an animal name and when the button is pressed,\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ the chunk whose name corresponds to the animal name will be loaded.\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">let<\/span> <span style=\"color:#a6e22e\">fileName<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ Here the animal name is written by the user.\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>document.<span style=\"color:#a6e22e\">querySelector<\/span>(<span style=\"color:#e6db74\">&#39;input&#39;<\/span>).<span style=\"color:#a6e22e\">addEventListener<\/span>(<span style=\"color:#e6db74\">&#39;input&#39;<\/span>, <span style=\"color:#a6e22e\">ev<\/span> <span style=\"color:#f92672\">=&gt;<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">fileName<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">ev<\/span>.<span style=\"color:#a6e22e\">target<\/span>.<span style=\"color:#a6e22e\">value<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>});\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ And here the chunk is loaded. Notice how the chunk depends on the animal name\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ written by the user.\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>document.<span style=\"color:#a6e22e\">getElementById<\/span>(<span style=\"color:#e6db74\">&#39;demo&#39;<\/span>).<span style=\"color:#a6e22e\">addEventListener<\/span>(<span style=\"color:#e6db74\">&#39;click&#39;<\/span>, () <span style=\"color:#f92672\">=&gt;<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">import<\/span>(<span style=\"color:#75715e\">\/* webpackChunkName: &#39;animal&#39; *\/<\/span> <span style=\"color:#e6db74\">`.\/animals\/<\/span><span style=\"color:#e6db74\">${<\/span><span style=\"color:#a6e22e\">fileName<\/span><span style=\"color:#e6db74\">}<\/span><span style=\"color:#e6db74\">.js`<\/span>)\n<\/span><\/span><span style=\"display:flex;\"><span>    .<span style=\"color:#a6e22e\">then<\/span>(<span style=\"color:#a6e22e\">m<\/span> <span style=\"color:#f92672\">=&gt;<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#a6e22e\">console<\/span>.<span style=\"color:#a6e22e\">warn<\/span>(<span style=\"color:#e6db74\">&#39;CHUNK LOADED!&#39;<\/span>, <span style=\"color:#a6e22e\">m<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#a6e22e\">m<\/span>.<span style=\"color:#66d9ef\">default<\/span>();\n<\/span><\/span><span style=\"display:flex;\"><span>    })\n<\/span><\/span><span style=\"display:flex;\"><span>    .<span style=\"color:#66d9ef\">catch<\/span>(<span style=\"color:#a6e22e\">console<\/span>.<span style=\"color:#a6e22e\">warn<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>});\n<\/span><\/span><\/code><\/pre><\/div><p>webpack will generate a <strong>chunk for each file<\/strong> in the <code>animals<\/code> directory. This is the <code>lazy<\/code> option&rsquo;s behaviour. What happens in this example is that the user will type the name of an animal into the input and when the button is clicked, the chunk which corresponds to that name will be loaded. If the name of the animal can&rsquo;t be found in the <code>animals<\/code> directory, an error will be thrown. You might be wondering now: <em>isn&rsquo;t it a waste of resources, if webpack creates multiple chunks when in the end there will be only one chunk that matches the path?<\/em> Well, practically it isn&rsquo;t, because all those possible chunks are just files held on the server which are not sent to the browser unless the browser requires them(e.g when the <code>import()<\/code>&rsquo;s path matches an existing file path).<\/p>\n<p>As with the <em>static<\/em> <code>import<\/code> situation where the path is known at compile time(e.g <code>import('.\/animals\/cat.js)<\/code>), when only one chunk would be created, when the <code>import<\/code>&rsquo;s path is dynamic, the loaded chunk will be cached, so no important resources will be wasted in case the same chunk is required multiple times.<\/p>\n<p>Precisely, webpack stores the loaded chunks in a map such that if the chunk that is requested has already been loaded, it will be immediately retrieved from the map. The map&rsquo;s keys are the IDs of the chunks and the values depend on the chunk&rsquo;s status: <code>0<\/code>(when the chunk is loaded), <code>Promise<\/code>(when the chunk is currently loading) and <code>undefined<\/code>(when the chunk hasn&rsquo;t even been requested from anywhere).<\/p>\n<p>Here&rsquo;s a way to visualize this example:<\/p>\n<p><p class=\"markdown-image\">\n  <img src=\"images\/lazy-opt.png\" alt=\"lazy-opt.png\"  \/>\n<\/p><\/p>\n<p><em>A link for the above diagram can be found <a href=\"https:\/\/excalidraw.com\/#json=5579912295481344,6TqFOfloQIGg1xXAtrboUQ\" target=\"_blank\" rel=\"noopener\">here<\/a>.<\/em><\/p>\n<p>We can notice from this diagram the 4 chunks that have been created(one for each file in the <code>animals<\/code> directory), along with the main parent chunk(called <code>index<\/code>). It is crucial to have a (root) parent chunk because it contains the required logic to fetch and integrate other child chunks in the application.<\/p>\n<p>The way webpack handles this behavior internally is by having a <strong>map<\/strong> where the keys are the filenames(in this case, the keys are the filenames from the <code>animals<\/code> directory) and the values are arrays(as we will see, the array&rsquo;s pattern will be<code>{ filename: [moduleId, chunkId] }<\/code>). An array of this kind contains very useful information to webpack, such as: the <strong>chunk id<\/strong>(it will be used in the HTTP request for the corresponding JS file), the <strong>module id<\/strong>(so that it knows what module to require as soon as the chunk has finished loading) and, finally, the <strong>module&rsquo;s exports type<\/strong>(it used by webpack in order to achieve compatibility when using other types of modules than ES modules). This concept of a map which is used to keep track of modules and their traits is used regardless of the mode we&rsquo;re using.<\/p>\n<p>To see an example of what that array would look like, you can open the StackBlitz app whose link can be found at the beginning of this section(or <a href=\"https:\/\/stackblitz.com\/edit\/node-eujyms?file=readme.md\" target=\"_blank\" rel=\"noopener\">here<\/a>) and run the <code>npm run build<\/code> script. Then, if you open the <code>dist\/main.js<\/code> file, you can already notice the map we talked about earlier:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">var<\/span> <span style=\"color:#a6e22e\">map<\/span> <span style=\"color:#f92672\">=<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>\t<span style=\"color:#e6db74\">&#34;.\/cat.js&#34;<\/span><span style=\"color:#f92672\">:<\/span> [\n<\/span><\/span><span style=\"display:flex;\"><span>\t\t<span style=\"color:#ae81ff\">2<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>\t\t<span style=\"color:#ae81ff\">0<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>\t],\n<\/span><\/span><span style=\"display:flex;\"><span>\t<span style=\"color:#e6db74\">&#34;.\/dog.js&#34;<\/span><span style=\"color:#f92672\">:<\/span> [\n<\/span><\/span><span style=\"display:flex;\"><span>\t\t<span style=\"color:#ae81ff\">3<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>\t\t<span style=\"color:#ae81ff\">1<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>\t],\n<\/span><\/span><span style=\"display:flex;\"><span>\t<span style=\"color:#e6db74\">&#34;.\/fish.js&#34;<\/span><span style=\"color:#f92672\">:<\/span> [\n<\/span><\/span><span style=\"display:flex;\"><span>\t\t<span style=\"color:#ae81ff\">4<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>\t\t<span style=\"color:#ae81ff\">2<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>\t],\n<\/span><\/span><span style=\"display:flex;\"><span>\t<span style=\"color:#e6db74\">&#34;.\/lion.js&#34;<\/span><span style=\"color:#f92672\">:<\/span> [\n<\/span><\/span><span style=\"display:flex;\"><span>\t\t<span style=\"color:#ae81ff\">5<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>\t\t<span style=\"color:#ae81ff\">3<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>\t]\n<\/span><\/span><span style=\"display:flex;\"><span>};\n<\/span><\/span><\/code><\/pre><\/div><p>Once again, this object follows this pattern: <code>{ filename: [moduleId, chunkId] }<\/code>. Concretely, if the user types <code>cat<\/code> and then presses the button, the chunk with the id <code>2<\/code> will be loaded and as soon as the chunk is ready, it will use the module with id <code>0<\/code>.<\/p>\n<p>It&rsquo;s also worth exploring a case where the array has the module&rsquo;s exports type specified. In this situation, the <code>cat.js<\/code> file is a CommonJS module and the rest are ES modules:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ cat.js\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span><span style=\"color:#a6e22e\">module<\/span>.<span style=\"color:#a6e22e\">exports<\/span> <span style=\"color:#f92672\">=<\/span> () <span style=\"color:#f92672\">=&gt;<\/span> <span style=\"color:#a6e22e\">console<\/span>.<span style=\"color:#a6e22e\">log<\/span>(<span style=\"color:#e6db74\">&#39;CAT&#39;<\/span>);\n<\/span><\/span><\/code><\/pre><\/div><p><em>The StackBlitz app for this new example can be found <a href=\"https:\/\/stackblitz.com\/edit\/node-shyjri?file=readme.md\" target=\"_blank\" rel=\"noopener\">here<\/a>.<\/em><\/p>\n<p>If you run <code>npm run build<\/code> and check the <code>dist\/main.js<\/code> file, the map will look a bit different:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">var<\/span> <span style=\"color:#a6e22e\">map<\/span> <span style=\"color:#f92672\">=<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>\t<span style=\"color:#e6db74\">&#34;.\/cat.js&#34;<\/span><span style=\"color:#f92672\">:<\/span> [\n<\/span><\/span><span style=\"display:flex;\"><span>\t\t<span style=\"color:#ae81ff\">2<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>\t\t<span style=\"color:#ae81ff\">7<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>\t\t<span style=\"color:#ae81ff\">0<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>\t],\n<\/span><\/span><span style=\"display:flex;\"><span>\t<span style=\"color:#e6db74\">&#34;.\/dog.js&#34;<\/span><span style=\"color:#f92672\">:<\/span> [\n<\/span><\/span><span style=\"display:flex;\"><span>\t\t<span style=\"color:#ae81ff\">3<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>\t\t<span style=\"color:#ae81ff\">9<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>\t\t<span style=\"color:#ae81ff\">1<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>\t],\n<\/span><\/span><span style=\"display:flex;\"><span>\t<span style=\"color:#e6db74\">&#34;.\/fish.js&#34;<\/span><span style=\"color:#f92672\">:<\/span> [\n<\/span><\/span><span style=\"display:flex;\"><span>\t\t<span style=\"color:#ae81ff\">4<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>\t\t<span style=\"color:#ae81ff\">9<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>\t\t<span style=\"color:#ae81ff\">2<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>\t],\n<\/span><\/span><span style=\"display:flex;\"><span>\t<span style=\"color:#e6db74\">&#34;.\/lion.js&#34;<\/span><span style=\"color:#f92672\">:<\/span> [\n<\/span><\/span><span style=\"display:flex;\"><span>\t\t<span style=\"color:#ae81ff\">5<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>\t\t<span style=\"color:#ae81ff\">9<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>\t\t<span style=\"color:#ae81ff\">3<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>\t]\n<\/span><\/span><span style=\"display:flex;\"><span>};\n<\/span><\/span><\/code><\/pre><\/div><p>Here, the pattern is this: <code>{ filename: [moduleId, moduleExportsMode, chunkId] }<\/code>. \u00a0Based on the module&rsquo;s exports type, webpack knows how to load the module after the chunk has been loaded. Basically, <code>9<\/code> indicates a simple ES module, case in which the module with the <code>moduleId<\/code> will be required. <code>7<\/code> indicates a CommonJS module and in this case webpack needs to create a <em>fake<\/em> ES module from it.<br>\nTo see it in practice, you can open the last provided example and start the server. If I want to use the <code>cat<\/code> module, after clicking on the button, I should see a new request for the chunk which contains the module in question:<\/p>\n<p><p class=\"markdown-image\">\n  <img src=\"images\/Screenshot-from-2021-09-14-23-47-44.png\" alt=\"Screenshot from 2021-09-14 23-47-44.png\"  \/>\n<\/p><\/p>\n<p>As probably noticed, the console tells us that the chunk has been loaded, as well as the module it contains, namely the <code>cat<\/code> module. The same steps are taken if we want to use, for instance, the <code>fish<\/code> module:<\/p>\n<p><p class=\"markdown-image\">\n  <img src=\"images\/Screenshot-from-2021-09-14-23-51-20.png\" alt=\"Screenshot from 2021-09-14 23-51-20.png\"  \/>\n<\/p><\/p>\n<p>And the same will happen for each file which matches the pattern resulted in the <code>import<\/code> function.<\/p>\n<h2 id=\"the-eager-mode\">\n  <span>\n  The <code>eager<\/code> mode\n  <\/span>\n  <a href=\"#the-eager-mode\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><p><em>If you want to follow along, you can find a StackBlitz demo <a href=\"https:\/\/stackblitz.com\/edit\/node-lc7hui?file=readme.md\" target=\"_blank\" rel=\"noopener\">here<\/a>(it&rsquo;s safe to run <code>npm run build<\/code> first).<\/em><\/p>\n<p>Let&rsquo;s first see the example which we&rsquo;ll use throughout this section:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">let<\/span> <span style=\"color:#a6e22e\">fileName<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ Here the animal name is written by the user.\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>document.<span style=\"color:#a6e22e\">querySelector<\/span>(<span style=\"color:#e6db74\">&#39;input&#39;<\/span>).<span style=\"color:#a6e22e\">addEventListener<\/span>(<span style=\"color:#e6db74\">&#39;input&#39;<\/span>, <span style=\"color:#a6e22e\">ev<\/span> <span style=\"color:#f92672\">=&gt;<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">fileName<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">ev<\/span>.<span style=\"color:#a6e22e\">target<\/span>.<span style=\"color:#a6e22e\">value<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>});\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ Here the chunk that depends on `fileName` is loaded.\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>document.<span style=\"color:#a6e22e\">getElementById<\/span>(<span style=\"color:#e6db74\">&#39;demo&#39;<\/span>).<span style=\"color:#a6e22e\">addEventListener<\/span>(<span style=\"color:#e6db74\">&#39;click&#39;<\/span>, () <span style=\"color:#f92672\">=&gt;<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">import<\/span>(<span style=\"color:#75715e\">\/* webpackChunkName: &#39;animal&#39;, webpackMode: &#39;eager&#39; *\/<\/span> <span style=\"color:#e6db74\">`.\/animals\/<\/span><span style=\"color:#e6db74\">${<\/span><span style=\"color:#a6e22e\">fileName<\/span><span style=\"color:#e6db74\">}<\/span><span style=\"color:#e6db74\">.js`<\/span>)\n<\/span><\/span><span style=\"display:flex;\"><span>    .<span style=\"color:#a6e22e\">then<\/span>(<span style=\"color:#a6e22e\">m<\/span> <span style=\"color:#f92672\">=&gt;<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#a6e22e\">console<\/span>.<span style=\"color:#a6e22e\">warn<\/span>(<span style=\"color:#e6db74\">&#39;FILE LOADED!&#39;<\/span>, <span style=\"color:#a6e22e\">m<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#a6e22e\">m<\/span>.<span style=\"color:#66d9ef\">default<\/span>();\n<\/span><\/span><span style=\"display:flex;\"><span>    })\n<\/span><\/span><span style=\"display:flex;\"><span>    .<span style=\"color:#66d9ef\">catch<\/span>(<span style=\"color:#a6e22e\">console<\/span>.<span style=\"color:#a6e22e\">warn<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>});\n<\/span><\/span><\/code><\/pre><\/div><p>As you can see, the mode can be specified with the <code>webpackMode: 'eager'<\/code> magic comment.<\/p>\n<p>When using the <code>eager<\/code> mode, there won&rsquo;t be any additional chunks created. All the modules which match the <code>import<\/code>&rsquo;s pattern will be part of the same main chunk. More specifically, considering the same file structure,<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-markdown\" data-lang=\"markdown\"><span style=\"display:flex;\"><span>\u251c\u2500\u2500 animals\n<\/span><\/span><span style=\"display:flex;\"><span>\u2502   \u251c\u2500\u2500 cat.js\n<\/span><\/span><span style=\"display:flex;\"><span>\u2502   \u251c\u2500\u2500 dog.js\n<\/span><\/span><span style=\"display:flex;\"><span>\u2502   \u251c\u2500\u2500 fish.js\n<\/span><\/span><span style=\"display:flex;\"><span>\u2502   \u2514\u2500\u2500 lion.js\n<\/span><\/span><span style=\"display:flex;\"><span>\u2514\u2500\u2500 index.js\n<\/span><\/span><\/code><\/pre><\/div><p>it&rsquo;s as if the current module would directly require the modules which are inside the <code>animals<\/code> directory, with the exception that none of the modules will be actually executed. They will just be placed into an object\/array of modules and when the button it clicked, it will execute and retrieve that module on the spot, without additional network requests or any other asynchronous operations.<\/p>\n<p>After running <code>npm run build<\/code> and after opening the <code>dist\/main.js<\/code> file, you should see a map object like this one:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">var<\/span> <span style=\"color:#a6e22e\">map<\/span> <span style=\"color:#f92672\">=<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>\t<span style=\"color:#e6db74\">&#34;.\/cat.js&#34;<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#ae81ff\">2<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>\t<span style=\"color:#e6db74\">&#34;.\/dog.js&#34;<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#ae81ff\">3<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>\t<span style=\"color:#e6db74\">&#34;.\/fish.js&#34;<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#ae81ff\">4<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>\t<span style=\"color:#e6db74\">&#34;.\/lion.js&#34;<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#ae81ff\">5<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>};\n<\/span><\/span><\/code><\/pre><\/div><p>Each value indicates the module&rsquo;s ID and if you scroll down a little, you&rsquo;ll find those modules:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/* 2 *\/<\/span> <span style=\"color:#75715e\">\/\/ -&gt; The `cat.js` file\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span><span style=\"color:#75715e\">\/***\/<\/span> ((<span style=\"color:#a6e22e\">__unused_webpack_module<\/span>, <span style=\"color:#a6e22e\">__webpack_exports__<\/span>, <span style=\"color:#a6e22e\">__webpack_require__<\/span>) <span style=\"color:#f92672\">=&gt;<\/span> {},\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/* 3 *\/<\/span> <span style=\"color:#75715e\">\/\/ -&gt; The `dog.js` file\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span><span style=\"color:#75715e\">\/***\/<\/span> ((<span style=\"color:#a6e22e\">__unused_webpack_module<\/span>, <span style=\"color:#a6e22e\">__webpack_exports__<\/span>, <span style=\"color:#a6e22e\">__webpack_require__<\/span>) <span style=\"color:#f92672\">=&gt;<\/span> {}\n<\/span><\/span><\/code><\/pre><\/div><p>So, the advantage of this approach is that the module, when required, it will be retrieved immediately, as opposed to making an extra HTTP request for each module, which is what happens when using the <code>lazy<\/code> mode.<\/p>\n<p>This can be verified in our example: after starting the server, try to require any of the modules present in the <code>animals<\/code> directory. The expected behavior is that no requests should appear in the <em>Network panel<\/em> and each existing module should be executed properly, as seen in the following image:<\/p>\n<p><p class=\"markdown-image\">\n  <img src=\"images\/Screenshot-from-2021-09-14-23-57-36.png\" alt=\"Screenshot from 2021-09-14 23-57-36.png\"  \/>\n<\/p><\/p>\n<p>Finally, here&rsquo;s a diagram to summarize this mode&rsquo;s behavior:<\/p>\n<p><p class=\"markdown-image\">\n  <img src=\"images\/eager.png\" alt=\"eager.png\"  \/>\n<\/p><\/p>\n<p><em>A link for the above diagram can be found <a href=\"https:\/\/excalidraw.com\/#json=6470887859552256,bk5OVUIJhKUbACnjlpU7dQ\" target=\"_blank\" rel=\"noopener\">here<\/a>.<\/em><\/p>\n<h2 id=\"the-lazy-once-mode\">\n  <span>\n  The <code>lazy-once<\/code> mode\n  <\/span>\n  <a href=\"#the-lazy-once-mode\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><p><em>The StackBlitz app for this section can be found <a href=\"https:\/\/stackblitz.com\/edit\/node-nhpq46?file=readme.md\" target=\"_blank\" rel=\"noopener\">here<\/a>.<\/em><\/p>\n<p>In the previous section we&rsquo;ve seen how to manually specify the mode, so the way to tell webpack we want to use the <code>lazy-once<\/code> mode should come as no surprise:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/*\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">The same file structure is assumed:\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\u251c\u2500\u2500 animals\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\u2502   \u251c\u2500\u2500 cat.js\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\u2502   \u251c\u2500\u2500 dog.js\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\u2502   \u251c\u2500\u2500 fish.js\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\u2502   \u2514\u2500\u2500 lion.js\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\u2514\u2500\u2500 index.js\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">*\/<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">let<\/span> <span style=\"color:#a6e22e\">fileName<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ Here the user chooses the name of the module.\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>document.<span style=\"color:#a6e22e\">querySelector<\/span>(<span style=\"color:#e6db74\">&#39;input&#39;<\/span>).<span style=\"color:#a6e22e\">addEventListener<\/span>(<span style=\"color:#e6db74\">&#39;input&#39;<\/span>, <span style=\"color:#a6e22e\">ev<\/span> <span style=\"color:#f92672\">=&gt;<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">fileName<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">ev<\/span>.<span style=\"color:#a6e22e\">target<\/span>.<span style=\"color:#a6e22e\">value<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>});\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ When clicked, the chunk will be loaded and the module that matches with the `fileName`\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ variable will be executed and retrieved.\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>document.<span style=\"color:#a6e22e\">getElementById<\/span>(<span style=\"color:#e6db74\">&#39;demo&#39;<\/span>).<span style=\"color:#a6e22e\">addEventListener<\/span>(<span style=\"color:#e6db74\">&#39;click&#39;<\/span>, () <span style=\"color:#f92672\">=&gt;<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">import<\/span>(<span style=\"color:#75715e\">\/* webpackChunkName: &#39;animal&#39;, webpackMode: &#39;lazy-once&#39; *\/<\/span> <span style=\"color:#e6db74\">`.\/animals\/<\/span><span style=\"color:#e6db74\">${<\/span><span style=\"color:#a6e22e\">fileName<\/span><span style=\"color:#e6db74\">}<\/span><span style=\"color:#e6db74\">.js`<\/span>)\n<\/span><\/span><span style=\"display:flex;\"><span>    .<span style=\"color:#a6e22e\">then<\/span>(<span style=\"color:#a6e22e\">m<\/span> <span style=\"color:#f92672\">=&gt;<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#a6e22e\">console<\/span>.<span style=\"color:#a6e22e\">warn<\/span>(<span style=\"color:#e6db74\">&#39;FILE LOADED!&#39;<\/span>, <span style=\"color:#a6e22e\">m<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#a6e22e\">m<\/span>.<span style=\"color:#66d9ef\">default<\/span>();\n<\/span><\/span><span style=\"display:flex;\"><span>    })\n<\/span><\/span><span style=\"display:flex;\"><span>    .<span style=\"color:#66d9ef\">catch<\/span>(<span style=\"color:#a6e22e\">console<\/span>.<span style=\"color:#a6e22e\">warn<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>});\n<\/span><\/span><\/code><\/pre><\/div><p>The behavior in this case is somehow similar to what we&rsquo;ve encountered in the previous section, <strong>except that all the modules which match the <code>import<\/code>&rsquo;s expression will be added to a child chunk and not into the main chunk. With this, it&rsquo;s also close to the <code>lazy<\/code> mode, as far as the lazy chunk goes.<\/strong><\/p>\n<p>Once the <code>npm run build<\/code> is run, the <code>dist<\/code> directory should have 2 files: <code>main.js<\/code>, which is the main chunk, and <code>animal.js<\/code>, which is the chunk in which all the modules corresponding to the files inside the <code>animals\/<\/code> directory reside. The upside of this way of loading modules is that you don&rsquo;t overload the main chunk with all the possible modules that can match the <code>import<\/code>&rsquo;s expression, but rather they are put in another chunk which can be loaded lazily. When the user presses the button to load a module, the entire chunk will be requested over the network and when it is ready, the module requested by the user will be executed and retrieved. <strong>Moreover, all the modules that this newly loaded chunk contains will be registered by webpack<\/strong>. The <strong>interesting thing<\/strong> is that if now the user requires a different module which also belongs to the just loaded chunk, there <strong>won&rsquo;t be any additional requests over the network<\/strong>. That&rsquo;s because the chunk will be served from a cache internally maintained by webpack and the required module will be retrieved from the array\/object of modules where webpack records them.<\/p>\n<p>Let&rsquo;s also try it in our example. I will first type <code>cat<\/code> and then press the button. In the <em>Network tab,<\/em> there should be a request for the <code>animal<\/code> chunk which, as stated earlier, contains all the necessary modules:<\/p>\n<p><p class=\"markdown-image\">\n  <img src=\"images\/Screenshot-from-2021-09-14-22-47-20.png\" alt=\"Screenshot from 2021-09-14 22-47-20.png\"  \/>\n<\/p><\/p>\n<p><em>Also notice that the <code>cat<\/code> module has been indeed invoked.<\/em><\/p>\n<p>Now if we want to use the <code>lion<\/code> module, I should not see a new request, but only a confirmation that the <code>lion<\/code> module has been executed:<\/p>\n<p><p class=\"markdown-image\">\n  <img src=\"images\/Screenshot-from-2021-09-14-22-49-33.png\" alt=\"Screenshot from 2021-09-14 22-49-33.png\"  \/>\n<\/p><\/p>\n<p>Here&rsquo;s a diagram to supplement what&rsquo;s been accumulated so far:<\/p>\n<p><p class=\"markdown-image\">\n  <img src=\"images\/lazy-once.png\" alt=\"lazy-once.png\"  \/>\n<\/p><\/p>\n<p><em>A link for the above diagram can be found <a href=\"https:\/\/excalidraw.com\/#json=6146532868882432,eCeP8OXmnRmnsdX7PVTJDg\" target=\"_blank\" rel=\"noopener\">here<\/a>.<\/em><\/p>\n<h2 id=\"the-weak-mode\">\n  <span>\n  The <code>weak<\/code> mode\n  <\/span>\n  <a href=\"#the-weak-mode\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><p>We&rsquo;ve saved this section until last because of its peculiarities. By using <code>weak<\/code> imports, we&rsquo;re essentially telling webpack that the resources we want to use should <strong>already<\/strong> be prepared for retrieval. This implies that the resources in question should by now be <strong>loaded<\/strong>(i.e <strong>required<\/strong> and <strong>used<\/strong>) from somewhere else, so as to when a <code>weak<\/code> import is used, this action doesn&rsquo;t trigger any fetching mechanisms(e.g making a network request in order to load a chunk), but only uses the module from the data structure that webpack uses to keep track of modules.<\/p>\n<p>We will start with a straightforward example which will initially throw an error and then we will expand on it in order to get a better understanding of what this <code>weak<\/code> mode is about:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">let<\/span> <span style=\"color:#a6e22e\">fileName<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ Here the user types the name of the module\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>document.<span style=\"color:#a6e22e\">querySelector<\/span>(<span style=\"color:#e6db74\">&#39;input&#39;<\/span>).<span style=\"color:#a6e22e\">addEventListener<\/span>(<span style=\"color:#e6db74\">&#39;input&#39;<\/span>, <span style=\"color:#a6e22e\">ev<\/span> <span style=\"color:#f92672\">=&gt;<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">fileName<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">ev<\/span>.<span style=\"color:#a6e22e\">target<\/span>.<span style=\"color:#a6e22e\">value<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>});\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ Here that module is retrieved directly if possible, otherwise\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ an error will be thrown.\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>document.<span style=\"color:#a6e22e\">getElementById<\/span>(<span style=\"color:#e6db74\">&#39;demo&#39;<\/span>).<span style=\"color:#a6e22e\">addEventListener<\/span>(<span style=\"color:#e6db74\">&#39;click&#39;<\/span>, () <span style=\"color:#f92672\">=&gt;<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">import<\/span>(<span style=\"color:#75715e\">\/* webpackChunkName: &#39;animal&#39;, webpackMode: &#39;weak&#39; *\/<\/span> <span style=\"color:#e6db74\">`.\/animals\/<\/span><span style=\"color:#e6db74\">${<\/span><span style=\"color:#a6e22e\">fileName<\/span><span style=\"color:#e6db74\">}<\/span><span style=\"color:#e6db74\">.js`<\/span>)\n<\/span><\/span><span style=\"display:flex;\"><span>    .<span style=\"color:#a6e22e\">then<\/span>(<span style=\"color:#a6e22e\">m<\/span> <span style=\"color:#f92672\">=&gt;<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#a6e22e\">console<\/span>.<span style=\"color:#a6e22e\">warn<\/span>(<span style=\"color:#e6db74\">&#39;FILE LOADED!&#39;<\/span>, <span style=\"color:#a6e22e\">m<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#a6e22e\">m<\/span>.<span style=\"color:#66d9ef\">default<\/span>();\n<\/span><\/span><span style=\"display:flex;\"><span>    })\n<\/span><\/span><span style=\"display:flex;\"><span>    .<span style=\"color:#66d9ef\">catch<\/span>(<span style=\"color:#a6e22e\">console<\/span>.<span style=\"color:#a6e22e\">warn<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>});\n<\/span><\/span><\/code><\/pre><\/div><p><em>A StackBlitz app with the example can be found <a href=\"https:\/\/stackblitz.com\/edit\/node-udhrm3?file=readme.md\" target=\"_blank\" rel=\"noopener\">here<\/a>(make sure to run <code>npm run build<\/code> and <code>npm run start<\/code> to start the server).<\/em><\/p>\n<p>Nothing elaborate until now, it&rsquo;s just what we&rsquo;ve been doing in other sections, namely specifying the mode we want the <code>import<\/code> function to operate, which in this case is <code>weak<\/code>.<\/p>\n<p>If you type <em>cat<\/em> in the input and then press the button, you&rsquo;ll notice an error in the console:<\/p>\n<p><p class=\"markdown-image\">\n  <img src=\"images\/Screenshot-from-2021-09-15-14-53-01.png\" alt=\"Screenshot from 2021-09-15 14-53-01.png\"  \/>\n<\/p><\/p>\n<p>And this should make sense because, as it&rsquo;s been mentioned previously, the <code>weak<\/code> import expects that the resource should already be ready to be used, not to make webpack take action in order to make it available. The way we&rsquo;re currently doing things, the <code>cat<\/code> module is not loaded from anywhere else, so this is <strong>why<\/strong> we&rsquo;re facing an error.<\/p>\n<p>In order to quickly mitigate this issue, we can add an <code>import * as c from '.\/animals\/cat';<\/code> statement at the beginning of the file:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ index.js\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">import<\/span> <span style=\"color:#f92672\">*<\/span> <span style=\"color:#66d9ef\">as<\/span> <span style=\"color:#a6e22e\">c<\/span> <span style=\"color:#66d9ef\">from<\/span> <span style=\"color:#e6db74\">&#39;.\/animals\/cat&#39;<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">let<\/span> <span style=\"color:#a6e22e\">fileName<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/* ... *\/<\/span>\n<\/span><\/span><\/code><\/pre><\/div><p>If we run <code>npm run build<\/code> and <code>npm run start<\/code> again and take the same steps, we should see that the <code>cat<\/code> module has been successfully executed. However, if you try with any other module than <code>cat<\/code>, the same error will appear:<\/p>\n<p><p class=\"markdown-image\">\n  <img src=\"images\/Screenshot-from-2021-09-15-15-03-53.png\" alt=\"Screenshot from 2021-09-15 15-03-53.png\"  \/>\n<\/p><\/p>\n<p>This feature could be used to enforce modules to be loaded beforehand, so that you ensure that at a certain point the modules accessible. Otherwise, an error will be thrown.<\/p>\n<p>As opposed to the other modes, the modules won&rsquo;t be added to the current chunk, neither to a child chunk, neither each into its own chunk. What webpack does in this case is to keep track of whether modules that match the <code>import<\/code>&rsquo;s expression exist or not and also keep track of modules&rsquo; exports type, if needed(e.g if they are all ES modules, then there is no need for it). For instance:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">var<\/span> <span style=\"color:#a6e22e\">map<\/span> <span style=\"color:#f92672\">=<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>\t<span style=\"color:#e6db74\">&#34;.\/cat.js&#34;<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#ae81ff\">1<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>\t<span style=\"color:#e6db74\">&#34;.\/dog.js&#34;<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#66d9ef\">null<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>\t<span style=\"color:#e6db74\">&#34;.\/fish.js&#34;<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#66d9ef\">null<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>\t<span style=\"color:#e6db74\">&#34;.\/lion.js&#34;<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#66d9ef\">null<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>};\n<\/span><\/span><\/code><\/pre><\/div><p>In the above map(which can be found in the <code>dist\/main.js<\/code> file - the only generated file), it is known <strong>for sure<\/strong> that the <code>cat<\/code> module is used across the app. <strong>However<\/strong>, it does not necessarily guarantee that the <code>cat<\/code> module is available. So the <strong>role<\/strong> of the <code>map<\/code> object from above is so keep track of modules which <em>have a purpose<\/em>(i.e if they are used at all) at all in the project. In other words, it keeps track of modules&rsquo; existence. The other modules whose values are <code>null<\/code> are called <strong>orphan modules<\/strong>.<\/p>\n<p><strong>There might be a case where the module exists, but it is not available<\/strong>. Consider the following example:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">let<\/span> <span style=\"color:#a6e22e\">fileName<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ Here the user chooses the name of the file.\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>document.<span style=\"color:#a6e22e\">querySelector<\/span>(<span style=\"color:#e6db74\">&#39;input&#39;<\/span>).<span style=\"color:#a6e22e\">addEventListener<\/span>(<span style=\"color:#e6db74\">&#39;input&#39;<\/span>, <span style=\"color:#a6e22e\">ev<\/span> <span style=\"color:#f92672\">=&gt;<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">fileName<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">ev<\/span>.<span style=\"color:#a6e22e\">target<\/span>.<span style=\"color:#a6e22e\">value<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>});\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ Requesting the module that should already be available.\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>document.<span style=\"color:#a6e22e\">getElementById<\/span>(<span style=\"color:#e6db74\">&#39;demo&#39;<\/span>).<span style=\"color:#a6e22e\">addEventListener<\/span>(<span style=\"color:#e6db74\">&#39;click&#39;<\/span>, () <span style=\"color:#f92672\">=&gt;<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">import<\/span>(<span style=\"color:#75715e\">\/* webpackChunkName: &#39;animal&#39;, webpackMode: &#39;weak&#39; *\/<\/span> <span style=\"color:#e6db74\">`.\/animals\/<\/span><span style=\"color:#e6db74\">${<\/span><span style=\"color:#a6e22e\">fileName<\/span><span style=\"color:#e6db74\">}<\/span><span style=\"color:#e6db74\">.js`<\/span>)\n<\/span><\/span><span style=\"display:flex;\"><span>    .<span style=\"color:#a6e22e\">then<\/span>(<span style=\"color:#a6e22e\">m<\/span> <span style=\"color:#f92672\">=&gt;<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#a6e22e\">console<\/span>.<span style=\"color:#a6e22e\">warn<\/span>(<span style=\"color:#e6db74\">&#39;FILE LOADED!&#39;<\/span>, <span style=\"color:#a6e22e\">m<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#a6e22e\">m<\/span>.<span style=\"color:#66d9ef\">default<\/span>();\n<\/span><\/span><span style=\"display:flex;\"><span>    })\n<\/span><\/span><span style=\"display:flex;\"><span>    .<span style=\"color:#66d9ef\">catch<\/span>(<span style=\"color:#a6e22e\">console<\/span>.<span style=\"color:#a6e22e\">warn<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>});\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ Dynamically loading the `cat.js` module.\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>document.<span style=\"color:#a6e22e\">getElementById<\/span>(<span style=\"color:#e6db74\">&#39;load-cat&#39;<\/span>).<span style=\"color:#a6e22e\">addEventListener<\/span>(<span style=\"color:#e6db74\">&#39;click&#39;<\/span>, () <span style=\"color:#f92672\">=&gt;<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">import<\/span>(<span style=\"color:#e6db74\">&#39;.\/animals\/cat.js&#39;<\/span>).<span style=\"color:#a6e22e\">then<\/span>(<span style=\"color:#a6e22e\">m<\/span> <span style=\"color:#f92672\">=&gt;<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">console<\/span>.<span style=\"color:#a6e22e\">warn<\/span>(<span style=\"color:#e6db74\">&#39;CAT CHUNK LOADED&#39;<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>  });\n<\/span><\/span><span style=\"display:flex;\"><span>});\n<\/span><\/span><\/code><\/pre><\/div><p><em>The StackBlitz app for this example can be found <a href=\"https:\/\/stackblitz.com\/edit\/node-za5moh?file=readme.md\" target=\"_blank\" rel=\"noopener\">here<\/a>.<\/em><\/p>\n<p>From the <code>import('.\/animals\/cat.js')<\/code> statement, we can tell that the module exists in the app, but in order for it to be <strong>available<\/strong>, the <code>#load-cat<\/code> button must be clicked first. By clicking it, the chunk will be fetched and the <code>cat<\/code> module will become accessible and that is because when a chunk is loaded, all of its modules will become available for the entire application.<\/p>\n<p>We can try to directly require the <code>cat<\/code> module(without pressing the <code>Load cat chunk<\/code> first), but we will end up with an error, saying <em>the module is not available:<\/em><\/p>\n<p><p class=\"markdown-image\">\n  <img src=\"images\/Screenshot-from-2021-09-15-15-49-47.png\" alt=\"Screenshot from 2021-09-15 15-49-47.png\"  \/>\n<\/p><\/p>\n<p>However, if we load the <code>cat<\/code> chunk first and then require the module, everything should be working fine:<\/p>\n<p><p class=\"markdown-image\">\n  <img src=\"images\/Screenshot-from-2021-09-15-15-50-35.png\" alt=\"Screenshot from 2021-09-15 15-50-35.png\"  \/>\n<\/p><\/p>\n<p>The takeaway from this section is that when using the <code>weak<\/code> mode, it is expected of the resource to be already at hand. Thus, there are 3 <em>filters<\/em> that a module must overcome: it must match with the <code>imports<\/code> expression, it must be used across the app(e.g it is directly imported or imported through a chunk) and it must be available(i.e already loaded from somewhere else).<\/p>\n<h2 id=\"conclusion\">\n  <span>\n  Conclusion\n  <\/span>\n  <a href=\"#conclusion\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><p>In this article we&rsquo;ve learned that the <code>import<\/code> function can do much more than simply creating a chunk. Hopefully, at this point, things make more sense when it comes to using <code>import<\/code> with dynamic arguments.<\/p>\n<p><strong>Thanks for reading!<\/strong><\/p>\n<p><em>The diagrams have been made with <a href=\"https:\/\/excalidraw.com\/\" target=\"_blank\" rel=\"noopener\">Excalidraw<\/a>.<\/em><\/p>\n<p><em>Special thanks <a href=\"https:\/\/twitter.com\/maxkoretskyi\" target=\"_blank\" rel=\"noopener\">Max Koretskyi<\/a> for reviewing this article and for providing extremely valuable feedback.<\/em><\/p>\n"},{"title":"An in-depth perspective on webpack's bundling process","link":"https:\/\/andreigatej.dev\/blog\/webpack-bundling-process\/","pubDate":"Mon, 27 Sep 2021 00:00:00 +0000","guid":"https:\/\/andreigatej.dev\/blog\/webpack-bundling-process\/","description":"<p><em>This article has been published on <a href=\"https:\/\/indepth.dev\/posts\/1482\/an-in-depth-perspective-on-webpacks-bundling-process\" target=\"_blank\" rel=\"noopener\">indepth.dev<\/a>.<\/em><\/p>\n<h2 id=\"introduction\">\n  <span>\n  Introduction\n  <\/span>\n  <a href=\"#introduction\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><p>Webpack is a very powerful and interesting tool that can be considered a fundamental component in many of today&rsquo;s technologies that web developers use to build their applications. However, many people would argue it is quite a challenge to work with it, mostly due to its complexity.<\/p>\n<p>In this series of articles I&rsquo;d like to share many details about the inner workings of webpack, with the hope that it will make working with webpack look more <em>approachable.<\/em> This article will serve as a basis for upcoming articles in which I will dive deeper into other webpack&rsquo;s features. You&rsquo;ll learn about how lazy loading works, how tree shaking works, how certain loaders work etc. My goal with this series is for you to become <em>more comfortable<\/em> when solving webpack-related problems. The objective of this article is to give you enough insights about the entire process so that you&rsquo;ll be able to intervene at any point in order to understand some aspects of webpack by yourself or to debug problems. Thus, in the last section we will see how to debug webpack&rsquo;s source code by going through its tests and some custom examples.<\/p>\n<p>We will start off with a diagram that depicts, not very briefly, the entire bundling process. Some details are omitted though, as they are subjects for future articles. Then, we will expand some of the steps from the diagram. As we go along, we will also explain concepts such as modules, chunks etc. Also, to simplify comprehension, I will replace the snippets from the source code with diagrams and simplified code snippets. I will include, however, some links to the source code, maybe they will turn out to be useful.<\/p>\n<p>As a convention, we will refer to <code>NormalModule<\/code>s simply as <em>modules.<\/em> There are other types of modules, such as <code>ExternalModule<\/code>(when using module federation)\u00a0and <code>ConcatenatedModule<\/code>(when using <code>require.context()<\/code>), which are topics for separated articles. In this article, we will only focus on <code>NormalModule<\/code>s.<\/p>\n<p>If you want to follow along and explore the source code as you read the article, there is a <strong>Debugging webpack&rsquo;s source code<\/strong> section that you should check out first.<\/p>\n<h2 id=\"visualizing-the-process-with-a-diagram\">\n  <span>\n  Visualizing the process with a diagram\n  <\/span>\n  <a href=\"#visualizing-the-process-with-a-diagram\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><p><p class=\"markdown-image\">\n  <img src=\"images\/base-diagram-1.png\" alt=\"base-diagram.png\"  \/>\n<\/p><\/p>\n<p><em>You can get a better experience when visualizing the diagram by viewing it &rsquo;live&rsquo; in Excalidraw. <a href=\"https:\/\/excalidraw.com\/#json=4517412917477376,mF3yLd-gYuRzCzWZ11fo7Q\" target=\"_blank\" rel=\"noopener\">Link here<\/a>.<\/em><\/p>\n<p>I&rsquo;d highly recommend opening the <a href=\"https:\/\/excalidraw.com\/#json=4517412917477376,mF3yLd-gYuRzCzWZ11fo7Q\" target=\"_blank\" rel=\"noopener\">Excalidraw link of the diagram<\/a>, as it will be used as support for the forthcoming in-depth explanations structured in sections, each of which describes a step or multiple steps from the diagram.<\/p>\n<p>Let&rsquo;s get started!<\/p>\n<h2 id=\"the-entry-object\">\n  <span>\n  The <code>entry<\/code> object\n  <\/span>\n  <a href=\"#the-entry-object\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><p>It is very important to mention that everything starts with the <code>entry<\/code> object. As you might expect, it supports many configurations, hence this topic deserves an article on its own. That&rsquo;s why we will consider a simpler example, that one in which the <code>entry<\/code> object is just a collection of key-value pairs:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ webpack.config.js\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span><span style=\"color:#a6e22e\">entry<\/span><span style=\"color:#f92672\">:<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>\t<span style=\"color:#a6e22e\">a<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;.\/a.js&#39;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>\t<span style=\"color:#a6e22e\">b<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;.\/b.js&#39;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>\t<span style=\"color:#75715e\">\/* ... *\/<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p>Conceptually, a <strong>module<\/strong> in webpack is associated with a file. So, in the diagram <code>'a.js'<\/code> will result in a new module and so will <code>'b.js'<\/code> . For now, it is enough to retain that <strong>a module is an <em>upgraded version<\/em> of a file. A module, once created and built, contains a lot of meaningful information besides the raw source code, such as: the loaders used, its dependencies, its exports(if any), its hash and much more<\/strong>. <strong>Each item<\/strong> in the <code>entry<\/code> object can be thought of as the <strong>root module<\/strong> in a tree of modules. A tree of modules because the root module might require some other modules(which can be fairly called <strong>dependencies<\/strong>), those modules might require other modules and so forth, so you can see how, at a higher level, such tree could be built. All these module trees are stored together in a <code>ModuleGraph<\/code>, which we will go over in the next section.<\/p>\n<p>The next thing that we need to mention now is that webpack is built on top of <strong>a lot of plugins<\/strong>. Although the bundling process is well established, there are a lot of ways one could chip in to add custom logic. Extensibility in webpack is implemented through <strong>hooks.<\/strong> For example, you can add custom logic after the <code>ModuleGraph<\/code> has been built, when a new asset has been generated for a chunk, before the module is about to be built(runs loaders and parses the source) etc. We will also explore them in future articles, as they are very interesting and they can provide solutions to a lot of problems related to webpack customization. Most of the times, the hooks are grouped under their purpose, and for any well defined purpose there is a <strong>plugin<\/strong>. For example, there is a plugin that is responsible for handling the <code>import()<\/code> function(responsible for parsing the comments and the argument) - it&rsquo;s called <a href=\"https:\/\/github.com\/webpack\/webpack\/blob\/main\/lib\/dependencies\/ImportParserPlugin.js#L27\" target=\"_blank\" rel=\"noopener\"><code>ImportParserPlugin<\/code><\/a> and all it does is to add a hook for when an <code>import()<\/code> call is encountered during the AST parsing.<\/p>\n<p>It should come as no surprise that there are a couple of plugins which are responsible for dealing with the <code>entry<\/code> object. There is the <code>EntryOptionPlugin<\/code> which practically takes in the <code>entry<\/code> object and creates an <code>EntryPlugin<\/code> <strong>for each item<\/strong> in the object. This part is important and is also related to what&rsquo;s been mentioned in the beginning of this section: each item of the <code>entry<\/code> object will result in a tree of modules(all these trees are separated from each other). Basically, the <code>EntryPlugin<\/code> <strong><a href=\"https:\/\/github.com\/webpack\/webpack\/blob\/main\/lib\/EntryPlugin.js#L48\" target=\"_blank\" rel=\"noopener\">starts the creation<\/a><\/strong> of a module tree, each of which will add information to the same single place, the <code>ModuleGraph<\/code>. Informally, we&rsquo;d say that the <code>EntryPlugin<\/code> starts this <em>complex process<\/em>.<\/p>\n<p><p class=\"markdown-image\">\n  <img src=\"images\/entry-option-plugin-1.png\" alt=\"entry-option-plugin.png\"  \/>\n<\/p><\/p>\n<p>For the sake of being on par with the initial diagram, it&rsquo;s worth mentioning that the <code>EntryPlugin<\/code> is also the place where an <code>EntryDependency<\/code> is created.<\/p>\n<p>Based on the above diagram, let&rsquo;s get more insights about how important the <code>EntryOptionsPlugin<\/code> is by loosely implementing it ourselves:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">class<\/span> <span style=\"color:#a6e22e\">CustomEntryOptionPlugin<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#75715e\">\/\/ This is the standard way of creating plugins.\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>  <span style=\"color:#75715e\">\/\/ It&#39;s either this, or a simple function, but we&#39;re using this approach\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>  <span style=\"color:#75715e\">\/\/ in order to be on par with how most of the plugins are created.\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>  <span style=\"color:#a6e22e\">apply<\/span>(<span style=\"color:#a6e22e\">compiler<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#75715e\">\/\/ Recall that hooks offer us the possibility to intervene in the\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>    <span style=\"color:#75715e\">\/\/ bundling process.\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>    <span style=\"color:#75715e\">\/\/ With the help of the `entryOption` hook, we&#39;re adding the logic\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>    <span style=\"color:#75715e\">\/\/ that will basically mean the start of the bundling process. As in,\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>    <span style=\"color:#75715e\">\/\/ the `entryObject` argument will hold the `entry` object from the\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>    <span style=\"color:#75715e\">\/\/ configuration file and we&#39;ll be using it to set up the creation of\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>    <span style=\"color:#75715e\">\/\/ module trees.\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>    <span style=\"color:#a6e22e\">compiler<\/span>.<span style=\"color:#a6e22e\">hooks<\/span>.<span style=\"color:#a6e22e\">entryOption<\/span>.<span style=\"color:#a6e22e\">tap<\/span>(<span style=\"color:#e6db74\">&#39;CustomEntryOptionPlugin&#39;<\/span>, <span style=\"color:#a6e22e\">entryObject<\/span> <span style=\"color:#f92672\">=&gt;<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#75715e\">\/\/ The `EntryOption` class will handle the creation of a module tree.\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>      <span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">EntryOption<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">class<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#66d9ef\">constructor<\/span> (<span style=\"color:#a6e22e\">options<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>          <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">options<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">options<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>        };\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#75715e\">\/\/ Since this is still a plugin, we&#39;re abiding by the standard.\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>        <span style=\"color:#a6e22e\">apply<\/span>(<span style=\"color:#a6e22e\">compiler<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>          <span style=\"color:#75715e\">\/\/ The `start` hook marks the start of the bundling process.\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>          <span style=\"color:#75715e\">\/\/ It will be called **after** `hooks.entryOption` is called.\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>          <span style=\"color:#a6e22e\">compiler<\/span>.<span style=\"color:#a6e22e\">hooks<\/span>.<span style=\"color:#a6e22e\">start<\/span>(<span style=\"color:#e6db74\">&#39;EntryOption&#39;<\/span>, ({ <span style=\"color:#a6e22e\">createModuleTree<\/span> }) <span style=\"color:#f92672\">=&gt;<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>            <span style=\"color:#75715e\">\/\/ Creating new tree of modules, based on the configuration of this plugin.\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>            <span style=\"color:#75715e\">\/\/ The `options` contain the name of the entry(which essentially is the name of the chunk)\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>            <span style=\"color:#75715e\">\/\/ and the file name.\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>            <span style=\"color:#75715e\">\/\/ The `EntryDependency` encapsulates these options and also provides way to\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>            <span style=\"color:#75715e\">\/\/ create modules(because it maps to a `NormalModuleFactory`, which produces `NormalModule`s).\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>            <span style=\"color:#75715e\">\/\/ After calling `createModuleTree`, the source code of the file will be found,\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>            <span style=\"color:#75715e\">\/\/ then a module instance will be created and then webpack will get its AST, which \n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>            <span style=\"color:#75715e\">\/\/ will be further used in the bundling process.\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>            <span style=\"color:#a6e22e\">createModuleTree<\/span>(<span style=\"color:#66d9ef\">new<\/span> <span style=\"color:#a6e22e\">EntryDependency<\/span>(<span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">options<\/span>));\n<\/span><\/span><span style=\"display:flex;\"><span>          });\n<\/span><\/span><span style=\"display:flex;\"><span>        };\n<\/span><\/span><span style=\"display:flex;\"><span>      };\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#75715e\">\/\/ For each item in the `entryObject` we&#39;re preparing\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>      <span style=\"color:#75715e\">\/\/ the creation of a module tree. Remember that each\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>      <span style=\"color:#75715e\">\/\/ module tree is independent of others.\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>\t\t\t<span style=\"color:#75715e\">\/\/ The `entryObject` could be something like this: `{ a: &#39;.\/a.js&#39; }`\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>      <span style=\"color:#66d9ef\">for<\/span> (<span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">name<\/span> <span style=\"color:#66d9ef\">in<\/span> <span style=\"color:#a6e22e\">entryObject<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">fileName<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">entryObject<\/span>[<span style=\"color:#a6e22e\">name<\/span>];\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#75715e\">\/\/ We&#39;re fundamentally saying: `ok webpack, when the bundling process starts,\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>        <span style=\"color:#75715e\">\/\/ be ready to create a module tree for this entry`.\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>        <span style=\"color:#66d9ef\">new<\/span> <span style=\"color:#a6e22e\">EntryOption<\/span>({ <span style=\"color:#a6e22e\">name<\/span>, <span style=\"color:#a6e22e\">fileName<\/span> }).<span style=\"color:#a6e22e\">apply<\/span>(<span style=\"color:#a6e22e\">compiler<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>      };\n<\/span><\/span><span style=\"display:flex;\"><span>    });\n<\/span><\/span><span style=\"display:flex;\"><span>  }\n<\/span><\/span><span style=\"display:flex;\"><span>};\n<\/span><\/span><\/code><\/pre><\/div><p>In the last part of this section, we will expand a bit upon what a <code>Dependency<\/code> is, because it&rsquo;s something we will use further in this article and will be mentioned in other articles. You might be wondering now what an <code>EntryDependency<\/code> is and why it is required. From my perspective, it all boils down to a <strong>smart abstraction<\/strong> when it comes to creating new modules. Simply put, a <strong>dependency<\/strong> is just a <strong>preliminary to<\/strong> an actual <code>module<\/code> instance. For instance, even the <code>entry<\/code> object&rsquo;s items are dependencies in webpack&rsquo;s view and they indicate the bare minimum for a <code>module<\/code> instance to be created: its path(e.g <code>.\/a.js<\/code>, <code>.\/b.js<\/code>). The creation of a module can&rsquo;t start without a <strong>dependency<\/strong>, because a dependency holds, among other significant information, the module&rsquo;s <strong>request<\/strong>, i.e the <strong>path<\/strong> to the file where the module&rsquo;s source can be found(e.g <code>'.\/a.js'<\/code>). A dependency also indicates how to construct that module and it does that with a <strong>module factory<\/strong>. A module factory knows how to start from a raw state(e.g the source code which is a simple string) and arrive at concrete entities which are then leveraged by webpack. The <a href=\"https:\/\/github.com\/webpack\/webpack\/blob\/main\/lib\/dependencies\/EntryDependency.js#L11\" target=\"_blank\" rel=\"noopener\"><code>EntryDependency<\/code> is<\/a> in fact a type of <a href=\"https:\/\/github.com\/webpack\/webpack\/blob\/main\/lib\/dependencies\/ModuleDependency.js#L16\" target=\"_blank\" rel=\"noopener\"><code>ModuleDependency<\/code><\/a>, meaning that it will for sure hold the module&rsquo;s <strong>request<\/strong> and the module factory it points to is <code>NormalModuleFactory<\/code>. Then, the <code>NormalModuleFactory<\/code> knows exactly what to do in order to create something meaningful to webpack from just a path. Another way to think about it is that a module was at first just a simple path(either in the <code>entry<\/code> object or part of an <code>import<\/code> statement), then it became a dependency and then, finally, a module.<br>\nHere&rsquo;s a way to visualize this:<\/p>\n<p><p class=\"markdown-image\">\n  <img src=\"images\/entry-dep.png\" alt=\"entry-dep.png\"  \/>\n<\/p><\/p>\n<p><em>An Excalidraw link for the above diagram can be found <a href=\"https:\/\/excalidraw.com\/#json=4907940771266560,zqDQZYTbwHupJqyFprykWA\" target=\"_blank\" rel=\"noopener\">here<\/a>.<\/em><\/p>\n<p>So, the <code>EntryDependency<\/code> is used at the beginning, when creating the <strong>root module<\/strong> of the module tree.<br>\nFor the rest of the modules, there are other types of dependencies. For example, if you use an <code>import<\/code> statement, like <code>import defaultFn from '.\/a.js'<\/code> , then there will be a <code>HarmonyImportSideEffectDependency<\/code> which holds the module&rsquo;s <strong>request<\/strong>(in this case, <code>'.\/a.js'<\/code>) and also maps to the <code>NormalModuleFactory<\/code>. So, there will be a new module for the file <code>'a.js'<\/code> and hopefully now you can see the important role that dependencies play. They essentially instruct webpack in how to create <code>modules<\/code>. We will reveal more information about dependencies later in the article.<\/p>\n<p><strong>A quick recap of what we&rsquo;ve learned in this section<\/strong>: for each item in the <code>entry<\/code> object, there will be an <code>EntryPlugin<\/code> instance, where an <code>EntryDependency<\/code> is created. This <code>EntryDependency<\/code> holds the module&rsquo;s <strong>request<\/strong>(i.e the path to the file) and also offers a way to make something useful of that request, by mapping to a module factory, namely <code>NormalModuleFactory<\/code>. A module factory knows how to create entities useful to webpack from just a file path. Once again, a dependency is crucial to creating a module because it holds important information, such as the module&rsquo;s request and how to process that request. There are several types of dependencies and not all of them are useful to creating a new module. From each \u00a0<code>EntryPlugin<\/code> \u00a0instance and with the help of the newly created <code>EntryDependency<\/code>, a module tree will be created. The module tree is built on top of modules and their dependencies, which are as well modules, which can also have dependencies.<\/p>\n<p>Now, let&rsquo;s continue our learning journey by finding out more about the <code>ModuleGraph<\/code>.<\/p>\n<h2 id=\"understanding-the-modulegraph\">\n  <span>\n  Understanding the <code>ModuleGraph<\/code>\n  <\/span>\n  <a href=\"#understanding-the-modulegraph\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><p>The <code>ModuleGraph<\/code> is a way to keep track of <strong>built modules<\/strong>. It heavily relies on dependencies in the sense that they provide ways to connect 2 different modules. For example:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ a.js\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span><span style=\"color:#66d9ef\">import<\/span> <span style=\"color:#a6e22e\">defaultBFn<\/span> <span style=\"color:#66d9ef\">from<\/span> <span style=\"color:#e6db74\">&#39;.b.js\/&#39;<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ b.js\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span><span style=\"color:#66d9ef\">export<\/span> <span style=\"color:#66d9ef\">default<\/span> <span style=\"color:#66d9ef\">function<\/span> () { <span style=\"color:#a6e22e\">console<\/span>.<span style=\"color:#a6e22e\">log<\/span>(<span style=\"color:#e6db74\">&#39;Hello from B!&#39;<\/span>); }\n<\/span><\/span><\/code><\/pre><\/div><p>Here we have 2 files, so 2 modules. File <code>a<\/code> requires something from file <code>b<\/code>, so in <code>a<\/code> there is a dependency which is established by the <code>import<\/code> statement. As far as the <code>ModuleGraph<\/code> is concerned, a dependency defines a way to connect 2 modules. Even the <code>EntryDependency<\/code> from the previous section connects 2 modules: the root module of the graph, which we will refer to as the <em>null module,<\/em> and the module associated with the entry file. The above snippet can be visualized as follows:<\/p>\n<p><p class=\"markdown-image\">\n  <img src=\"images\/dep.png\" alt=\"dep.png\"  \/>\n<\/p><\/p>\n<p>It&rsquo;s important to clarify the distinction between a simple module(i.e a <code>NormalModule<\/code> instance) and a module that belongs to the <code>ModuleGraph<\/code>. A <code>ModuleGraph<\/code>&rsquo;s node is called <a href=\"https:\/\/github.com\/webpack\/webpack\/blob\/main\/lib\/ModuleGraph.js#L60\" target=\"_blank\" rel=\"noopener\"><code>ModuleGraphModule<\/code><\/a> and it is just a <em>decorated<\/em> <code>NormalModule<\/code> instance. The <code>ModuleGraph<\/code> keeps track of these <em>decorated<\/em> modules with the help of a <a href=\"https:\/\/github.com\/webpack\/webpack\/blob\/main\/lib\/ModuleGraph.js#L90\" target=\"_blank\" rel=\"noopener\">map<\/a>, which has this signature: <code>Map&lt;Module, ModuleGraphModule&gt;<\/code>. These aspects were necessary to mention because, for instance, if there are only <code>NormalModule<\/code> instances, then there isn&rsquo;t much you can do with them, they don&rsquo;t know how to communicate with each other. The <code>ModuleGraph<\/code> gives meaning to these bare modules, by interconnecting them with the help of the aforementioned map which assigns each <code>NormalModule<\/code> with a <code>ModuleGraphModule<\/code>. This will make more sense at the end of the <em>Building the <code>ModuleGraph<\/code><\/em> section, where we will use the <code>ModuleGraph<\/code> and its internal map in particular in order to traverse the graph. We will refer to a module that belongs to the <code>ModuleGraph<\/code> simply as <code>module<\/code>, since the difference consists of only a few additional properties.<br>\nFor a node that belongs to the <code>ModuleGraph<\/code> there are few things well defined: the <strong>incoming connections<\/strong> and the <strong>outgoing connections<\/strong>. A connection is another small entity of the <code>ModuleGraph<\/code> and it holds meaningful information such as: the origin module, the <em>destination<\/em> module and the dependency that connects the 2 beforementioned modules. Concretely, based on the above diagram, a new connection has been created:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ This is based on the diagram and the snippet from above.\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span><span style=\"color:#a6e22e\">Connection<\/span><span style=\"color:#f92672\">:<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>\t<span style=\"color:#a6e22e\">originModule<\/span>: <span style=\"color:#66d9ef\">A<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>\t<span style=\"color:#a6e22e\">destinationModule<\/span>: <span style=\"color:#66d9ef\">B<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>\t<span style=\"color:#a6e22e\">dependency<\/span>: <span style=\"color:#66d9ef\">ImportDependency<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p>And the above connection will be added to <code>A.outgoingConnections<\/code> set and to <code>B.incomingConnections<\/code> set.<br>\nThese are the basic concepts of the <code>ModuleGraph<\/code>. As already mentioned in the previous section, all of the module trees created from the entries will output meaningful information to the same single place, the <code>ModuleGraph<\/code>. This is because all these trees of modules will eventually be connected with the <em>null module<\/em>(the root module of the <code>ModuleGraph<\/code>). The connection to the <em>null module<\/em> is established through the <code>EntryDependency<\/code> and the module created from the entry file. Here is how I think of the <code>ModuleGraph<\/code>:<\/p>\n<p><p class=\"markdown-image\">\n  <img src=\"images\/module-graph--1-.png\" alt=\"module-graph.png\"  \/>\n<\/p><\/p>\n<p><em><a href=\"https:\/\/excalidraw.com\/#json=6723625398829056,kgoBBvUYMyhqGk6dOvY2Sg\" target=\"_blank\" rel=\"noopener\">Here<\/a> is the Excalidraw link for the above diagram. Note: this diagram is not based on a previous example.<\/em><\/p>\n<p>As you can see, the <em>null module<\/em> has a connection to the root module of each module tree generated from an item in the <code>entry<\/code> object. Each edge in the graph represents a connection between 2 modules and each connection holds information about the source node, destination node and the dependency(which informally answers the question <em>why are these 2 modules connected?<\/em>).<\/p>\n<p>Now that we&rsquo;re a bit more familiar with the <code>ModuleGraph<\/code>, let&rsquo;s see how it is built.<\/p>\n<h2 id=\"building-the-modulegraph\">\n  <span>\n  Building the <code>ModuleGraph<\/code>\n  <\/span>\n  <a href=\"#building-the-modulegraph\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><p>As we have seen in the previous section, the <code>ModuleGraph<\/code> starts with a <em>null module<\/em> whose direct descendants are the root modules of the module trees which were built from <code>entry<\/code> object items. For that reason, in order to understand how the <code>ModuleGraph<\/code> is built, we are going to examine the building process of a single module tree.<\/p>\n<h3 id=\"the-first-modules-to-be-created\">\n  <span>\n  The first modules to be created\n  <\/span>\n  <a href=\"#the-first-modules-to-be-created\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h3><p>We will start with a very simple <code>entry<\/code> object:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">entry<\/span><span style=\"color:#f92672\">:<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>\t<span style=\"color:#a6e22e\">a<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;.\/a.js&#39;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p>Based on what&rsquo;s been said in the first section, at some point we would end up with an <code>EntryDependency<\/code> whose <strong>request<\/strong> is <code>'.\/a.js'<\/code>. This <code>EntryDependency<\/code> provides a way to create something meaningful from that <strong>request<\/strong> \u00a0because it maps to a module factory, namely <code>NormalModuleFactory<\/code>. This is where we left off in the first section.<\/p>\n<p>The next step in the process is where the <code>NormalModuleFactory<\/code> comes into play. The <code>NormalModuleFactory<\/code>, if it successfully completes its task, will create a <code>NormalModule<\/code>.<br>\n<strong>And just to make sure there are no uncertainties, the <code>NormalModule<\/code> is just a <em>deserialized<\/em> version of a file&rsquo;s source code, which is nothing more than a raw string<\/strong>. A raw string does not bring much value, so webpack can&rsquo;t do much with it. A <code>NormalModule<\/code> will also store the source code as a string, but, at the same time, it will also contain other meaningful information and functionality, such as: the loaders applied to it, the logic for building a module, the logic for generating runtime code, its hash value and much more. <strong>In other words, the <code>NormalModule<\/code> is the useful version of a simple raw file, from webpack&rsquo;s perspective.<\/strong><\/p>\n<p>In order for the <code>NormalModuleFactory<\/code> to output a <code>NormalModule<\/code>, it has to go through some steps. There is also stuff to do after the module has been created, such as building the module and processing its dependencies, if it has any.<\/p>\n<p>Here is once again the diagram we&rsquo;ve been following, now focusing on the <em>Building the <code>ModuleGraph<\/code><\/em> part:<\/p>\n<p><p class=\"markdown-image\">\n  <img src=\"images\/base-diagram-2.png\" alt=\"main.png\"  \/>\n<\/p><\/p>\n<p><em>You can find the link of the above diagram <a href=\"https:\/\/excalidraw.com\/#json=4517412917477376,mF3yLd-gYuRzCzWZ11fo7Q\" target=\"_blank\" rel=\"noopener\">here<\/a>.<\/em><\/p>\n<p><code>NormalModuleFactory<\/code> starts its magic by invoking its <a href=\"https:\/\/github.com\/webpack\/webpack\/blob\/main\/lib\/NormalModuleFactory.js#L747\" target=\"_blank\" rel=\"noopener\"><code>create<\/code> method<\/a>. Then, the <em>resolving process<\/em> begins. Here is where the <strong>request<\/strong>(file&rsquo;s path) is resolved, as well as the loaders for that type of file. Notice that only the file paths of the loaders will be determined, the <strong>loaders are not being invoked yet<\/strong> in this step.<\/p>\n<h3 id=\"the-modules-_build-process_\">\n  <span>\n  The module&rsquo;s <em>build process<\/em>\n  <\/span>\n  <a href=\"#the-modules-_build-process_\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h3><p>After all the necessary file paths have been resolved, the <code>NormalModule<\/code> is created. However, at this point, the module is not very valuable. A lot of relevant information will come after the module has been built. The <strong>build process<\/strong> of a <code>NormalModule<\/code> \u00a0comprises a few other steps:<\/p>\n<ul>\n<li>firstly, the loaders will be invoked on the raw source code; if there are multiple loaders, then the output of one loader might be the input another loader(the order in which loaders are provided in the config file is important);<\/li>\n<li>secondly, the resulting string after running through all the loaders will be parsed with <a href=\"https:\/\/github.com\/acornjs\/acorn\" target=\"_blank\" rel=\"noopener\">acorn<\/a>(a JavaScript parser) which yields the AST of the given file;<\/li>\n<li>finally, the AST will be analyzed; the analysis is necessary because during this phase the current module&rsquo;s <strong>dependencies<\/strong>(e.g other modules) <strong>will be determined<\/strong>, webpack can detect its magic functions(e.g <code>require.context<\/code>, <code>module.hot<\/code>) etc; \u00a0the AST analysis happens in the <a href=\"https:\/\/github.com\/webpack\/webpack\/blob\/main\/lib\/javascript\/JavascriptParser.js#L151\" target=\"_blank\" rel=\"noopener\"><code>JavascriptParser<\/code><\/a> and if you&rsquo;ll click on the link, you should see that a lot of cases are handled there; this part of the process is one of the most important, because a lot of what&rsquo;s coming next in the bundling process depends on this part;<\/li>\n<\/ul>\n<h3 id=\"dependencies-discovery-through-the-resulted-ast\">\n  <span>\n  Dependencies discovery through the resulted AST\n  <\/span>\n  <a href=\"#dependencies-discovery-through-the-resulted-ast\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h3><p>A way to think of the <em>discovery process<\/em>, without going too much into detail, would be this:<\/p>\n<p><p class=\"markdown-image\">\n  <img src=\"images\/ast--1-.png\" alt=\"ast.png\"  \/>\n<\/p><\/p>\n<p><em>A link to the above diagram can be found <a href=\"https:\/\/excalidraw.com\/#json=4927078877102080,H60JvyEHemF2nqVMrGGhLg\" target=\"_blank\" rel=\"noopener\">here<\/a>.<\/em><\/p>\n<p>Where <code>moduleInstance<\/code> refers to the <code>NormalModule<\/code> created from the <code>index.js<\/code> file. The <code>dep<\/code> in red refers to dependency created from the first <code>import<\/code> statement, and the <code>dep<\/code> in blue refers to the second <code>import<\/code> statement. This is just a simplified way of viewing things. In reality, as mentioned earlier, the dependencies are added after the AST has been obtained.<\/p>\n<p>Now that the AST has been examined, is time to continue the process of building the module tree we&rsquo;ve talked about at the beginning of this section. The next step is to <strong>process the dependencies<\/strong> that have been found at the previous step. If we were to follow the above diagram, the <code>index<\/code> module has 2 dependencies, which are also modules, namely <code>math.js<\/code> and <code>utils.js<\/code>. But before the dependencies become <strong>actual modules<\/strong>, we just have the <code>index<\/code> module whose <code>module.dependencies<\/code> has 2 values which hold information such as the module <strong>request<\/strong>(the file&rsquo;s path), the import specifier(e.g <code>sum<\/code>, <code>greet<\/code>). In order to turn them into modules, we need to use the <code>ModuleFactory<\/code> that these dependencies map to and <strong>repeat<\/strong> the same steps described above(the repetition is indicated by the dashed arrow in the diagram showed at the beginning of this section). After processing the current module&rsquo;s dependencies, those dependencies might have dependencies as well and this process goes on until there are no more dependencies. This is how the module tree is being built, while of course making sure that the connections between parent and child modules are properly set.<\/p>\n<p>Based on the knowledge we&rsquo;ve gained so far, it would be a good exercise to actually experiment with the <code>ModuleGraph<\/code> ourselves. For this purpose, let&rsquo;s see a way to implement a custom plugin that will allow us to traverse the <code>ModuleGraph<\/code>. Here&rsquo;s the diagram that depicts how modules depend on each other:<\/p>\n<p><p class=\"markdown-image\">\n  <img src=\"images\/module-graph--2-.png\" alt=\"module-graph.png\"  \/>\n<\/p><\/p>\n<p><em>The link for the above diagram can be found <a href=\"https:\/\/excalidraw.com\/#json=6301025929527296,nGs_YzUx5ET_qwZMv-RpMA\" target=\"_blank\" rel=\"noopener\">here<\/a>.<\/em><\/p>\n<p>To make sure that everything in the diagram is intelligible, the <code>a.js<\/code> file imports the <code>b.js<\/code> file, which imports both <code>b1.js<\/code> and <code>c.js<\/code>, then <code>c.js<\/code> imports <code>c1.j<\/code> and <code>d.js<\/code> and finally, <code>d.js<\/code> imports <code>d1.js<\/code>. Lastly, <code>ROOT<\/code> refers to the <em>null module,<\/em> which is the root of the <code>ModuleGraph<\/code>. The <code>entry<\/code> options consists of only one value, <code>a.js<\/code>:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ webpack.config.js\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span><span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">config<\/span> <span style=\"color:#f92672\">=<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">entry<\/span>: <span style=\"color:#66d9ef\">path.resolve<\/span>(<span style=\"color:#a6e22e\">__dirname<\/span>, <span style=\"color:#e6db74\">&#39;.\/src\/a.js&#39;<\/span>),\n<\/span><\/span><span style=\"display:flex;\"><span>\t<span style=\"color:#75715e\">\/* ... *\/<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>};\n<\/span><\/span><\/code><\/pre><\/div><div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ The way we&#39;re adding logic to the existing webpack hooks\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ is by using the `tap` method, which has this signature:\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ `tap(string, callback)`\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ where `string` is mainly for debugging purposes, indicating\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ the source where the custom logic has been added from.\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ The `callback`&#39;s argument depend on the hook on which we&#39;re adding custom functionality.\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">class<\/span> <span style=\"color:#a6e22e\">UnderstandingModuleGraphPlugin<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">apply<\/span>(<span style=\"color:#a6e22e\">compiler<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">className<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#66d9ef\">constructor<\/span>.<span style=\"color:#a6e22e\">name<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#75715e\">\/\/ Onto the `compilation` object: it is where most of the *state* of\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>    <span style=\"color:#75715e\">\/\/ the bundling process is kept. It contains information such as the module graph,\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>    <span style=\"color:#75715e\">\/\/ the chunk graph, the created chunks, the created modules, the generated assets\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>    <span style=\"color:#75715e\">\/\/ and much more.\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>    <span style=\"color:#a6e22e\">compiler<\/span>.<span style=\"color:#a6e22e\">hooks<\/span>.<span style=\"color:#a6e22e\">compilation<\/span>.<span style=\"color:#a6e22e\">tap<\/span>(<span style=\"color:#a6e22e\">className<\/span>, (<span style=\"color:#a6e22e\">compilation<\/span>) <span style=\"color:#f92672\">=&gt;<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#75715e\">\/\/ The `finishModules` is called after *all* the modules(including\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>      <span style=\"color:#75715e\">\/\/ their dependencies and the dependencies&#39; dependencies and so forth)\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>      <span style=\"color:#75715e\">\/\/ have been built.\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>      <span style=\"color:#a6e22e\">compilation<\/span>.<span style=\"color:#a6e22e\">hooks<\/span>.<span style=\"color:#a6e22e\">finishModules<\/span>.<span style=\"color:#a6e22e\">tap<\/span>(<span style=\"color:#a6e22e\">className<\/span>, (<span style=\"color:#a6e22e\">modules<\/span>) <span style=\"color:#f92672\">=&gt;<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#75715e\">\/\/ `modules` is the set which contains all the built modules.\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>        <span style=\"color:#75715e\">\/\/ These are simple `NormalModule` instances. Once again, a `NormalModule`\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>        <span style=\"color:#75715e\">\/\/ is produced by the `NormalModuleFactory`.\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>        <span style=\"color:#75715e\">\/\/ console.log(modules);\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#75715e\">\/\/ Retrieving the **module map**(Map&lt;Module, ModuleGraphModule&gt;).\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>        <span style=\"color:#75715e\">\/\/ It contains all the information we need in order to traverse the graph.\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>        <span style=\"color:#66d9ef\">const<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>          <span style=\"color:#a6e22e\">moduleGraph<\/span><span style=\"color:#f92672\">:<\/span> { <span style=\"color:#a6e22e\">_moduleMap<\/span>: <span style=\"color:#66d9ef\">moduleMap<\/span> },\n<\/span><\/span><span style=\"display:flex;\"><span>        } <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">compilation<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#75715e\">\/\/ Let&#39;s traverse the module graph in a DFS fashion.\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>        <span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">dfs<\/span> <span style=\"color:#f92672\">=<\/span> () <span style=\"color:#f92672\">=&gt;<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>          <span style=\"color:#75715e\">\/\/ Recall that the root module of the `ModuleGraph` is the\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>          <span style=\"color:#75715e\">\/\/ *null module*.\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>          <span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">root<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">null<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>          <span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">visited<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">new<\/span> <span style=\"color:#a6e22e\">Map<\/span>();\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>          <span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">traverse<\/span> <span style=\"color:#f92672\">=<\/span> (<span style=\"color:#a6e22e\">crtNode<\/span>) <span style=\"color:#f92672\">=&gt;<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>            <span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#a6e22e\">visited<\/span>.<span style=\"color:#66d9ef\">get<\/span>(<span style=\"color:#a6e22e\">crtNode<\/span>)) {\n<\/span><\/span><span style=\"display:flex;\"><span>              <span style=\"color:#66d9ef\">return<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>            }\n<\/span><\/span><span style=\"display:flex;\"><span>            <span style=\"color:#a6e22e\">visited<\/span>.<span style=\"color:#66d9ef\">set<\/span>(<span style=\"color:#a6e22e\">crtNode<\/span>, <span style=\"color:#66d9ef\">true<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>            <span style=\"color:#a6e22e\">console<\/span>.<span style=\"color:#a6e22e\">log<\/span>(\n<\/span><\/span><span style=\"display:flex;\"><span>              <span style=\"color:#a6e22e\">crtNode<\/span><span style=\"color:#f92672\">?<\/span>.<span style=\"color:#a6e22e\">resource<\/span> <span style=\"color:#f92672\">?<\/span> <span style=\"color:#a6e22e\">path<\/span>.<span style=\"color:#a6e22e\">basename<\/span>(<span style=\"color:#a6e22e\">crtNode<\/span><span style=\"color:#f92672\">?<\/span>.<span style=\"color:#a6e22e\">resource<\/span>) <span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;ROOT&#39;<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>            );\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>            <span style=\"color:#75715e\">\/\/ Getting the associated `ModuleGraphModule`, which only has some extra\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>            <span style=\"color:#75715e\">\/\/ properties besides a `NormalModule` that we can use to traverse the graph further.\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>            <span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">correspondingGraphModule<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">moduleMap<\/span>.<span style=\"color:#66d9ef\">get<\/span>(<span style=\"color:#a6e22e\">crtNode<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>            <span style=\"color:#75715e\">\/\/ A `Connection`&#39;s `originModule` is the where the arrow starts\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>            <span style=\"color:#75715e\">\/\/ and a `Connection`&#39;s `module` is there the arrow ends.\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>            <span style=\"color:#75715e\">\/\/ So, the `module` of a `Connection` is a child node.\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>            <span style=\"color:#75715e\">\/\/ Here you can find more about the graph&#39;s connection: https:\/\/github.com\/webpack\/webpack\/blob\/main\/lib\/ModuleGraphConnection.js#L53.\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>            <span style=\"color:#75715e\">\/\/ `correspondingGraphModule.outgoingConnections` is either a Set or undefined(in case the node has no children).\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>            <span style=\"color:#75715e\">\/\/ We&#39;re using `new Set` because a module can be reference the same module through multiple connections.\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>            <span style=\"color:#75715e\">\/\/ For instance, an `import foo from &#39;file.js&#39;` will result in 2 connections: one for a simple import\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>            <span style=\"color:#75715e\">\/\/ and one for the `foo` default specifier. This is an implementation detail which you shouldn&#39;t worry about.\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>            <span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">children<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">new<\/span> <span style=\"color:#a6e22e\">Set<\/span>(\n<\/span><\/span><span style=\"display:flex;\"><span>              Array.<span style=\"color:#66d9ef\">from<\/span>(\n<\/span><\/span><span style=\"display:flex;\"><span>                <span style=\"color:#a6e22e\">correspondingGraphModule<\/span>.<span style=\"color:#a6e22e\">outgoingConnections<\/span> <span style=\"color:#f92672\">||<\/span> [],\n<\/span><\/span><span style=\"display:flex;\"><span>                (<span style=\"color:#a6e22e\">c<\/span>) <span style=\"color:#f92672\">=&gt;<\/span> <span style=\"color:#a6e22e\">c<\/span>.<span style=\"color:#a6e22e\">module<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>              )\n<\/span><\/span><span style=\"display:flex;\"><span>            );\n<\/span><\/span><span style=\"display:flex;\"><span>            <span style=\"color:#66d9ef\">for<\/span> (<span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">c<\/span> <span style=\"color:#66d9ef\">of<\/span> <span style=\"color:#a6e22e\">children<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>              <span style=\"color:#a6e22e\">traverse<\/span>(<span style=\"color:#a6e22e\">c<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>            }\n<\/span><\/span><span style=\"display:flex;\"><span>          };\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>          <span style=\"color:#75715e\">\/\/ Starting the traversal.\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>          <span style=\"color:#a6e22e\">traverse<\/span>(<span style=\"color:#a6e22e\">root<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>        };\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#a6e22e\">dfs<\/span>();\n<\/span><\/span><span style=\"display:flex;\"><span>      });\n<\/span><\/span><span style=\"display:flex;\"><span>    });\n<\/span><\/span><span style=\"display:flex;\"><span>  }\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p>The example we&rsquo;re following now be found at this <a href=\"https:\/\/stackblitz.com\/edit\/node-rxfljv?file=webpack.config.js\" target=\"_blank\" rel=\"noopener\">StackBlitz app<\/a>. Make sure to run <code>npm run build<\/code> in order to see the plugin in action. Based on the module hierarchy, after running the <code>build<\/code> command, this is the output we should be getting:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">a<\/span>.<span style=\"color:#a6e22e\">js<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">b<\/span>.<span style=\"color:#a6e22e\">js<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">b1<\/span>.<span style=\"color:#a6e22e\">js<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">c<\/span>.<span style=\"color:#a6e22e\">js<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">c1<\/span>.<span style=\"color:#a6e22e\">js<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">d<\/span>.<span style=\"color:#a6e22e\">js<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">d1<\/span>.<span style=\"color:#a6e22e\">js<\/span>\n<\/span><\/span><\/code><\/pre><\/div><p>Now that the <code>ModuleGraph<\/code> has been built and hopefully you&rsquo;ve got a grasp on it, it&rsquo;s time to find out what happens next. According to the <em>main diagram<\/em>, the next step would be to create chunks, so let&rsquo;s get into it. But before doing that, it&rsquo;s worth clarifying some important concepts, such a <code>Chunk<\/code>, <code>ChunkGroup<\/code> and <code>EntryPoint<\/code>.<\/p>\n<h2 id=\"clarifying-what-chunk-chunkgroup-entrypoint-are\">\n  <span>\n  Clarifying what <code>Chunk<\/code>, <code>ChunkGroup<\/code>, <code>EntryPoint<\/code> are\n  <\/span>\n  <a href=\"#clarifying-what-chunk-chunkgroup-entrypoint-are\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><p>Now that we are a bit more familiar with what modules are, we will build on top of that to explain the concepts mentioned in this section&rsquo;s title. To quickly explain once again what modules are, it suffices to know that <strong>a module is an <em>upgraded version<\/em> of a file. A module, once created and built, contains a lot of meaningful information besides the raw source code, such as: the loaders used, its dependencies, its exports(if any), its hash and much more.<\/strong><\/p>\n<p><strong>A <code>Chunk<\/code> encapsulates one or module modules<\/strong>. At first glance, one might think that the number of entry files(an entry file = an item of the <code>entry<\/code> object) is proportional with the number of resulting chunks. This statement is partially true, because the <code>entry<\/code> object might have only one item and the number of resulting chunks could be greater than one. It is indeed true that for each <strong><code>entry<\/code> item<\/strong> there will be a corresponding chunk in the <em>dist<\/em> directory, but other chunks could be created implicitly, for example when using the <code>import()<\/code> function. But <strong>regardless<\/strong> of how it is created, each chunk will have a corresponding file in the <em>dist<\/em> directory. We will expand upon this in the <em>Building the <code>ChunkGraph<\/code><\/em> section, where we will clarify which modules will belong to a <code>chunk<\/code> and which won&rsquo;t.<\/p>\n<p>A <code>ChunkGroup<\/code> contains one or more chunks. A <code>ChunkGroup<\/code> can be a parent or a child to another <code>ChunkGroup<\/code>. For example, when using dynamic imports, for each <code>import()<\/code> function used there will be a <code>ChunkGroup<\/code> created, whose parent will be an existing <code>ChunkGroup<\/code>, the one which comprises the file(i.e the module) in which the <code>import()<\/code> functions are used. A visualization of this fact can be seen in the <em>Building the <code>ChunkGraph<\/code><\/em> section.<\/p>\n<p>An <code>EntryPoint<\/code> is a <strong>type of<\/strong> <code>ChunkGroup<\/code> which is created <strong>for each item<\/strong> in the <code>entry<\/code> object. The fact that a chunk belongs to an <code>EntryPoint<\/code> has implications on the rendering process, as we will make it more clearer in a future article.<\/p>\n<p>Given that we&rsquo;re more familiar with these concepts, let&rsquo;s proceed and understand the <code>ChunkGraph<\/code>.<\/p>\n<h2 id=\"building-the-chunkgraph\">\n  <span>\n  Building the <code>ChunkGraph<\/code>\n  <\/span>\n  <a href=\"#building-the-chunkgraph\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><p>Recall that all we have until this moment is just a <code>ModuleGraph<\/code>, which we talked about in a previous section. However, the <code>ModuleGraph<\/code> is just a necessary part of the bundling process. It has to be leveraged in order for features like code splitting to be possible.<\/p>\n<p>At this point of the bundling process, for each item from the <code>entry<\/code> object there will be an <code>EntryPoint<\/code>. Since it is a type of <code>ChunkGroup<\/code>, it will contain at least a chunk. So, if the <code>entry<\/code> object has 3 items, there will be 3 <code>EntryPoint<\/code> instances, each of which has a chunk, also called the <strong>entrypoint chunk<\/strong>, whose name is the <code>entry<\/code> item key&rsquo;s value. The modules associated with the entry files are called <strong>entry modules<\/strong> and each of them will belong to their <strong>entrypoint chunk<\/strong>. They matter because they are the starting point of the <code>ChunkGraph<\/code>&rsquo;s building process. Note that a chunk can have more than one <strong>entry module<\/strong>:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ webpack.config.js\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span><span style=\"color:#a6e22e\">entry<\/span><span style=\"color:#f92672\">:<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">foo<\/span><span style=\"color:#f92672\">:<\/span> [<span style=\"color:#e6db74\">&#39;.\/a.js&#39;<\/span>, <span style=\"color:#e6db74\">&#39;.\/b.js&#39;<\/span>],\n<\/span><\/span><span style=\"display:flex;\"><span>},\n<\/span><\/span><\/code><\/pre><\/div><p>In the above example, there will be chunk named <code>foo<\/code>(the item&rsquo;s key) will have 2 entry modules: the one associated with the <code>a.js<\/code> file and the other associated with the <code>b.js<\/code> file. And of course, the chunk will belong to the <code>EntryPoint<\/code> instance created based on the <code>entry<\/code> item.<\/p>\n<p>Before going into detail, let&rsquo;s set out an example based on which we will discuss the building process:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">entry<\/span><span style=\"color:#f92672\">:<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">foo<\/span><span style=\"color:#f92672\">:<\/span> [<span style=\"color:#a6e22e\">path<\/span>.<span style=\"color:#a6e22e\">join<\/span>(<span style=\"color:#a6e22e\">__dirname<\/span>, <span style=\"color:#e6db74\">&#39;src&#39;<\/span>, <span style=\"color:#e6db74\">&#39;a.js&#39;<\/span>), <span style=\"color:#a6e22e\">path<\/span>.<span style=\"color:#a6e22e\">join<\/span>(<span style=\"color:#a6e22e\">__dirname<\/span>, <span style=\"color:#e6db74\">&#39;src&#39;<\/span>, <span style=\"color:#e6db74\">&#39;a1.js&#39;<\/span>)],\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">bar<\/span>: <span style=\"color:#66d9ef\">path.join<\/span>(<span style=\"color:#a6e22e\">__dirname<\/span>, <span style=\"color:#e6db74\">&#39;src&#39;<\/span>, <span style=\"color:#e6db74\">&#39;c.js&#39;<\/span>),\n<\/span><\/span><span style=\"display:flex;\"><span>  },\n<\/span><\/span><\/code><\/pre><\/div><p>This example will encompass things that were mentioned earlier: the parent-child relationship of <code>ChunkGroups<\/code>(and hence dynamic imports), chunks and <code>EntryPoints<\/code>.<\/p>\n<p><em>You can try out the above example <a href=\"https:\/\/stackblitz.com\/edit\/node-z6d8js?file=readme.md\" target=\"_blank\" rel=\"noopener\">here<\/a>. The diagram that comes next is based on this example.<\/em><\/p>\n<p>The <code>ChunkGraph<\/code> is built in an recursive fashion. It starts by adding <strong>all the entry modules<\/strong> to a queue. Then, when an entry module is processed, meaning that its dependencies(which are modules as well) will be examined and each dependency will be added to the queue too. This keeps on repeating until the queue becomes empty. This part of the process is where the modules are <em>visited.<\/em> However, this is just the first part. Recall that <code>ChunkGroup<\/code>s can be a parent to\/child of other <code>ChunkGroup<\/code>s. These <em>connections<\/em> are resolved in the second part. For example, as previously stated, a dynamic import(i.e <code>import()<\/code> function) will result in a new child <code>ChunkGroup<\/code>. In webpack&rsquo;s parlance, the <code>import()<\/code> expression defines an <strong>asynchronous block of dependencies<\/strong>. From my perspective, it&rsquo;s called a <em>block<\/em> because the first thing that comes to mind is something that contains other objects. In case of <code>import('.\/foo.js'.then(module =&gt; ...)<\/code>, it&rsquo;s clear that our intention is to load something <strong>asynchronously<\/strong> and it&rsquo;s obvious that in order to use the <code>module<\/code> variable, all the dependencies(i.e modules) of <code>foo<\/code>(including <code>foo<\/code> itself) must be resolved, before the actual module is available. We will thoroughly discuss how the <code>import()<\/code> function works, along with its particularities(e.g magic comments and other options), in a future article.<br>\n<em>If this sparked your curiosity, <a href=\"https:\/\/github.com\/webpack\/webpack\/blob\/main\/lib\/dependencies\/ImportParserPlugin.js#L27\" target=\"_blank\" rel=\"noopener\">here<\/a> is where the block is created during the AST analysis<\/em>.<br>\n<em>The source code which summarizes the building process of the <code>ChunkGraph<\/code> can be found <a href=\"https:\/\/github.com\/webpack\/webpack\/blob\/main\/lib\/buildChunkGraph.js#L1277-L1299\" target=\"_blank\" rel=\"noopener\">here<\/a>.<\/em><\/p>\n<p>For now, let&rsquo;s just see the diagram of the <code>ChunkGraph<\/code> created from our above configuration:<\/p>\n<p><p class=\"markdown-image\">\n  <img src=\"images\/chunk-graph--1-.png\" alt=\"chunk-graph.png\"  \/>\n<\/p><\/p>\n<p><em>The link to the above diagram can be found <a href=\"https:\/\/excalidraw.com\/#json=6255037734977536,S8OwG9rWcdgphRWDBoiZwg\" target=\"_blank\" rel=\"noopener\">here<\/a>.<\/em><\/p>\n<p>The diagram illustrates a very simplified version of the <code>ChunkGraph<\/code>, but it should be sufficient to highlight the resulting chunks and the relationships between <code>ChunkGroup<\/code>s. We can see 4 chunks, so there will be 4 output files. The <code>foo<\/code> chunk will have 4 modules, of which 2 are <strong>entry modules.<\/strong> The <code>bar<\/code> chunk will only have 1 entry module and the other one can be considered a <em>normal<\/em> module. We can also notice that each <code>import()<\/code> expression will result in a new <code>ChunkGroup<\/code>(whose parent is the <em>bar<\/em> <code>EntryPoint<\/code>), which involves a new chunk.<\/p>\n<p>The content of the yielded files is determined based on the <code>ChunkGraph<\/code>, so this is why it is very important to the whole bundling process. We will briefly talk about the chunk assets(i.e the yielded files) in the following section.<\/p>\n<p>Before exploring a practical example where we&rsquo;d use the <code>ChunkGraph<\/code>, it&rsquo;s important to mention a few of its particularities. Similar to the <code>ModuleGraph<\/code>, a node that belongs to the <code>ChunkGraph<\/code> is called <a href=\"https:\/\/github.com\/webpack\/webpack\/blob\/main\/lib\/ChunkGraph.js#L199\" target=\"_blank\" rel=\"noopener\"><code>ChunkGraphChunk<\/code><\/a>(read as <em>a chunk that belongs to the <code>ChunkGraph<\/code><\/em>) and it is just a <em>decorated<\/em> chunk, meaning that it as some extra properties such as the modules which are part of the chunk, the entry modules of a chunk and others. Just like the <code>ModuleGraph<\/code>, the <code>ChunkGraph<\/code> keeps track of these <em>chunks with additional properties<\/em> with the help of a map which has this signature: <code>WeakMap&lt;Chunk, ChunkGraphChunk&gt;<\/code>. In comparison with the <code>ModuleGraph<\/code>&rsquo;s map, this map maintained by the <code>ChunkGraph<\/code> does not contain information about the connections between chunks. Instead, all the necessary information(such as the <code>ChunkGroup<\/code>s it belongs to) \u00a0is kept within the chunk itself. Remember that chunks are grouped together in <code>ChunkGroups<\/code> and between these chunk groups there can be parent-child relationships(just as we&rsquo;ve seen in the above diagram). This is not the case for modules, because modules can depend on each other, but there is not a strict concept of <em>parent modules.<\/em><\/p>\n<p>Let&rsquo;s now try to use the <code>ChunkGraph<\/code> in a custom plugin in order to get a better understanding of it. Note that this example we&rsquo;re considering is the one the above diagram depicts:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">path<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">require<\/span>(<span style=\"color:#e6db74\">&#39;path&#39;<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ We&#39;re printing this way in order to highlight the parent-child\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ relationships between `ChunkGroup`s.\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span><span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">printWithLeftPadding<\/span> <span style=\"color:#f92672\">=<\/span> (<span style=\"color:#a6e22e\">message<\/span>, <span style=\"color:#a6e22e\">paddingLength<\/span>) <span style=\"color:#f92672\">=&gt;<\/span> <span style=\"color:#a6e22e\">console<\/span>.<span style=\"color:#a6e22e\">log<\/span>(<span style=\"color:#a6e22e\">message<\/span>.<span style=\"color:#a6e22e\">padStart<\/span>(<span style=\"color:#a6e22e\">message<\/span>.<span style=\"color:#a6e22e\">length<\/span> <span style=\"color:#f92672\">+<\/span> <span style=\"color:#a6e22e\">paddingLength<\/span>));\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">class<\/span> <span style=\"color:#a6e22e\">UnderstandingChunkGraphPlugin<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">apply<\/span> (<span style=\"color:#a6e22e\">compiler<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">className<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#66d9ef\">constructor<\/span>.<span style=\"color:#a6e22e\">name<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">compiler<\/span>.<span style=\"color:#a6e22e\">hooks<\/span>.<span style=\"color:#a6e22e\">compilation<\/span>.<span style=\"color:#a6e22e\">tap<\/span>(<span style=\"color:#a6e22e\">className<\/span>, <span style=\"color:#a6e22e\">compilation<\/span> <span style=\"color:#f92672\">=&gt;<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#75715e\">\/\/ The `afterChunks` hook is called after the `ChunkGraph` has been built.\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>      <span style=\"color:#a6e22e\">compilation<\/span>.<span style=\"color:#a6e22e\">hooks<\/span>.<span style=\"color:#a6e22e\">afterChunks<\/span>.<span style=\"color:#a6e22e\">tap<\/span>(<span style=\"color:#a6e22e\">className<\/span>, <span style=\"color:#a6e22e\">chunks<\/span> <span style=\"color:#f92672\">=&gt;<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#75715e\">\/\/ `chunks` is a set of all created chunks. The chunks are added into\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>        <span style=\"color:#75715e\">\/\/ this set based on the order in which they are created.\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>        <span style=\"color:#75715e\">\/\/ console.log(chunks);\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>        \n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#75715e\">\/\/ As we&#39;ve said earlier in the article, the `compilation` object\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>        <span style=\"color:#75715e\">\/\/ contains the state of the bundling process. Here we can also find\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>        <span style=\"color:#75715e\">\/\/ all the `ChunkGroup`s(including the `Entrypoint` instances) that have been created.\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>        <span style=\"color:#75715e\">\/\/ console.log(compilation.chunkGroups);\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>        \n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#75715e\">\/\/ An `EntryPoint` is a type of `ChunkGroup` which is created for each\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>        <span style=\"color:#75715e\">\/\/ item in the `entry` object. In our current example, there are 2.\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>        <span style=\"color:#75715e\">\/\/ So, in order to traverse the `ChunkGraph`, we will have to start\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>        <span style=\"color:#75715e\">\/\/ from the `EntryPoints`, which are stored in the `compilation` object.\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>        <span style=\"color:#75715e\">\/\/ More about the `entrypoints` map(&lt;string, Entrypoint&gt;): https:\/\/github.com\/webpack\/webpack\/blob\/main\/lib\/Compilation.js#L956-L957\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>        <span style=\"color:#66d9ef\">const<\/span> { <span style=\"color:#a6e22e\">entrypoints<\/span> } <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">compilation<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>        \n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#75715e\">\/\/ More about the `chunkMap`(&lt;Chunk, ChunkGraphChunk&gt;): https:\/\/github.com\/webpack\/webpack\/blob\/main\/lib\/ChunkGraph.js#L226-L227\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>        <span style=\"color:#66d9ef\">const<\/span> { <span style=\"color:#a6e22e\">chunkGraph<\/span><span style=\"color:#f92672\">:<\/span> { <span style=\"color:#a6e22e\">_chunks<\/span>: <span style=\"color:#66d9ef\">chunkMap<\/span> } } <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">compilation<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>        \n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">printChunkGroupsInformation<\/span> <span style=\"color:#f92672\">=<\/span> (<span style=\"color:#a6e22e\">chunkGroup<\/span>, <span style=\"color:#a6e22e\">paddingLength<\/span>) <span style=\"color:#f92672\">=&gt;<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>          <span style=\"color:#a6e22e\">printWithLeftPadding<\/span>(<span style=\"color:#e6db74\">`Current ChunkGroup&#39;s name: <\/span><span style=\"color:#e6db74\">${<\/span><span style=\"color:#a6e22e\">chunkGroup<\/span>.<span style=\"color:#a6e22e\">name<\/span><span style=\"color:#e6db74\">}<\/span><span style=\"color:#e6db74\">;`<\/span>, <span style=\"color:#a6e22e\">paddingLength<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>          <span style=\"color:#a6e22e\">printWithLeftPadding<\/span>(<span style=\"color:#e6db74\">`Is current ChunkGroup an EntryPoint? - <\/span><span style=\"color:#e6db74\">${<\/span><span style=\"color:#a6e22e\">chunkGroup<\/span>.<span style=\"color:#66d9ef\">constructor<\/span>.<span style=\"color:#a6e22e\">name<\/span> <span style=\"color:#f92672\">===<\/span> <span style=\"color:#e6db74\">&#39;Entrypoint&#39;<\/span><span style=\"color:#e6db74\">}<\/span><span style=\"color:#e6db74\">`<\/span>, <span style=\"color:#a6e22e\">paddingLength<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>          \n<\/span><\/span><span style=\"display:flex;\"><span>          <span style=\"color:#75715e\">\/\/ `chunkGroup.chunks` - a `ChunkGroup` can contain one or mode chunks.\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>          <span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">allModulesInChunkGroup<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">chunkGroup<\/span>.<span style=\"color:#a6e22e\">chunks<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>            .<span style=\"color:#a6e22e\">flatMap<\/span>(<span style=\"color:#a6e22e\">c<\/span> <span style=\"color:#f92672\">=&gt;<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>              <span style=\"color:#75715e\">\/\/ Using the information stored in the `ChunkGraph`\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>              <span style=\"color:#75715e\">\/\/ in order to get the modules contained by a single chunk.\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>              <span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">associatedGraphChunk<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">chunkMap<\/span>.<span style=\"color:#66d9ef\">get<\/span>(<span style=\"color:#a6e22e\">c<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>              \n<\/span><\/span><span style=\"display:flex;\"><span>              <span style=\"color:#75715e\">\/\/ This includes the *entry modules* as well.\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>              <span style=\"color:#75715e\">\/\/ Using the spread operator because `.modules` is a Set in this case.\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>              <span style=\"color:#66d9ef\">return<\/span> [...<span style=\"color:#a6e22e\">associatedGraphChunk<\/span>.<span style=\"color:#a6e22e\">modules<\/span>];\n<\/span><\/span><span style=\"display:flex;\"><span>            })\n<\/span><\/span><span style=\"display:flex;\"><span>            <span style=\"color:#75715e\">\/\/ The resource of a module is an absolute path and\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>            <span style=\"color:#75715e\">\/\/ we&#39;re only interested in the file name associated with\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>            <span style=\"color:#75715e\">\/\/ our module.\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>            .<span style=\"color:#a6e22e\">map<\/span>(<span style=\"color:#a6e22e\">module<\/span> <span style=\"color:#f92672\">=&gt;<\/span> <span style=\"color:#a6e22e\">path<\/span>.<span style=\"color:#a6e22e\">basename<\/span>(<span style=\"color:#a6e22e\">module<\/span>.<span style=\"color:#a6e22e\">resource<\/span>));\n<\/span><\/span><span style=\"display:flex;\"><span>          <span style=\"color:#a6e22e\">printWithLeftPadding<\/span>(<span style=\"color:#e6db74\">`The modules that belong to this chunk group: <\/span><span style=\"color:#e6db74\">${<\/span><span style=\"color:#a6e22e\">allModulesInChunkGroup<\/span>.<span style=\"color:#a6e22e\">join<\/span>(<span style=\"color:#e6db74\">&#39;, &#39;<\/span>)<span style=\"color:#e6db74\">}<\/span><span style=\"color:#e6db74\">`<\/span>, <span style=\"color:#a6e22e\">paddingLength<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>          \n<\/span><\/span><span style=\"display:flex;\"><span>          <span style=\"color:#a6e22e\">console<\/span>.<span style=\"color:#a6e22e\">log<\/span>(<span style=\"color:#e6db74\">&#39;\\n&#39;<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>          \n<\/span><\/span><span style=\"display:flex;\"><span>          <span style=\"color:#75715e\">\/\/ A `ChunkGroup` can have children `ChunkGroup`s.\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>          [...<span style=\"color:#a6e22e\">chunkGroup<\/span>.<span style=\"color:#a6e22e\">_children<\/span>].<span style=\"color:#a6e22e\">forEach<\/span>(<span style=\"color:#a6e22e\">childChunkGroup<\/span> <span style=\"color:#f92672\">=&gt;<\/span> <span style=\"color:#a6e22e\">printChunkGroupsInformation<\/span>(<span style=\"color:#a6e22e\">childChunkGroup<\/span>, <span style=\"color:#a6e22e\">paddingLength<\/span> <span style=\"color:#f92672\">+<\/span> <span style=\"color:#ae81ff\">3<\/span>));\n<\/span><\/span><span style=\"display:flex;\"><span>        };\n<\/span><\/span><span style=\"display:flex;\"><span>        \n<\/span><\/span><span style=\"display:flex;\"><span>\t\t<span style=\"color:#75715e\">\/\/ Traversing the `ChunkGraph` in a DFS manner.\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>        <span style=\"color:#66d9ef\">for<\/span> (<span style=\"color:#66d9ef\">const<\/span> [<span style=\"color:#a6e22e\">entryPointName<\/span>, <span style=\"color:#a6e22e\">entryPoint<\/span>] <span style=\"color:#66d9ef\">of<\/span> <span style=\"color:#a6e22e\">entrypoints<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>          <span style=\"color:#a6e22e\">printChunkGroupsInformation<\/span>(<span style=\"color:#a6e22e\">entryPoint<\/span>, <span style=\"color:#ae81ff\">0<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>        }\n<\/span><\/span><span style=\"display:flex;\"><span>      });\n<\/span><\/span><span style=\"display:flex;\"><span>    });\n<\/span><\/span><span style=\"display:flex;\"><span>  }\n<\/span><\/span><span style=\"display:flex;\"><span>}; \n<\/span><\/span><\/code><\/pre><\/div><p>The example can be found at this <a href=\"https:\/\/stackblitz.com\/edit\/node-nlpz6x?file=webpack.config.js\" target=\"_blank\" rel=\"noopener\">StackBlitz app<\/a>. After running <code>npm run build<\/code>, this is the output that you should see:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-markdown\" data-lang=\"markdown\"><span style=\"display:flex;\"><span>Current ChunkGroup&#39;s name: foo;\n<\/span><\/span><span style=\"display:flex;\"><span>Is current ChunkGroup an EntryPoint? - true\n<\/span><\/span><span style=\"display:flex;\"><span>The modules that belong to this chunk group: a.js, b.js, a1.js, b1.js\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>Current ChunkGroup&#39;s name: bar;\n<\/span><\/span><span style=\"display:flex;\"><span>Is current ChunkGroup an EntryPoint? - true\n<\/span><\/span><span style=\"display:flex;\"><span>The modules that belong to this chunk group: c.js, common.js\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>   Current ChunkGroup&#39;s name: c1;\n<\/span><\/span><span style=\"display:flex;\"><span>   Is current ChunkGroup an EntryPoint? - false\n<\/span><\/span><span style=\"display:flex;\"><span>   The modules that belong to this chunk group: c1.js\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>   Current ChunkGroup&#39;s name: c2;\n<\/span><\/span><span style=\"display:flex;\"><span>   Is current ChunkGroup an EntryPoint? - false\n<\/span><\/span><span style=\"display:flex;\"><span>   The modules that belong to this chunk group: c2.js\n<\/span><\/span><\/code><\/pre><\/div><p>We&rsquo;ve used indentation in order to distinguish the parent-child relationships. We can also notice that the output is on par with the diagram, so we can be sure of the traversal&rsquo;s correctness.<\/p>\n<h2 id=\"emitting-chunk-assets\">\n  <span>\n  Emitting chunk assets\n  <\/span>\n  <a href=\"#emitting-chunk-assets\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><p>It is important to mention that the resulting files are not simply a copy-paste version of the original files because, in order to achieve its features, webpack needs to add some custom code that makes everything working as expected.<\/p>\n<p>This begs the question of how does webpack know what code to generate. Well, it all starts from the most basic(and useful) layer: the <code>module<\/code> . A module can export members, import other members, use dynamic imports, use webpack-specific functions(e.g <code>require.resolve<\/code>) etc. Based on the module&rsquo;s source code, webpack can determine which code to generate in order to achieve the desired features. This <em>discovery<\/em> starts during the AST analysis, where the dependencies are found. Although we&rsquo;ve been using <em>dependencies<\/em> and <em>modules<\/em> interchangeably until now, things are a bit more complex under the hood.<\/p>\n<p>For example, a simple <code>import { aFunction } from '.\/foo'<\/code> will result in 2 dependencies(one is for the <code>import<\/code> statement itself and the other is for the specifier, i.e <code>aFunction<\/code>), from which a single module will be created. Another example would be the <code>import()<\/code> function. This will result, as it was mentioned in the earlier sections, in an asynchronous block of dependencies and one of these dependencies is the <code>ImportDependency<\/code>, which is specific to a dynamic import.<br>\nThese <strong>dependencies are essential<\/strong> because they come with some <em>hints<\/em> about what code should be generated. For example, the <code>ImportDependency<\/code> knows exactly what to tell webpack in order to asynchronously fetch the imported module and use its exported members. These <em>hints<\/em> can be called <strong>runtime requirements.<\/strong> For instance, if the module exports some of its members, there will be some dependency(recall we&rsquo;re not referring to <em>modules<\/em> now), namely <code>HarmonyExportSpecifierDependency<\/code>, that will inform webpack that it needs to handle the logic for exporting members.<\/p>\n<p>To summarize, a module will come with its <strong>runtime requirements<\/strong>, which depend on what that module is using in its source code. The <strong>runtime requirements of a chunk<\/strong> will be the set of all the runtime requirements of <strong>all<\/strong> the modules that belong to that chunk. Now that webpack knows about all the requirements of a chunk, it will be able to properly generate the runtime code.<\/p>\n<p>This is also called the <em>rendering process<\/em> and we will discuss it in detail in a dedicated article. For now, it&rsquo;s enough to understand that the rendering process heavily relies on the <code>ChunkGraph<\/code>, because it contains groups of chunks(i.e <code>ChunkGroup<\/code>, <code>EntryPoint<\/code>), which contain chunks, which contain modules, which, in a granular way, contain information and hints about the runtime code that will be generated by webpack.<\/p>\n<p>This section marks the end of the theoretical part of this article. In the following section, we will see a few ways to debug webpack&rsquo;s source code, which can come handy whenever you&rsquo;re dealing with a problem or you just want to find out more about how webpack works.<\/p>\n<h2 id=\"debugging-webpacks-source-code\">\n  <span>\n  Debugging webpack&rsquo;s source code\n  <\/span>\n  <a href=\"#debugging-webpacks-source-code\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><p>In the hope that the previous sections shed some light on how webpack works under the hood, in this section we will see how to debug its source code. We will also see where to place breakpoints in order to examine specific parts of the bundling process.<\/p>\n<h3 id=\"using-vs-code\">\n  <span>\n  Using VS Code\n  <\/span>\n  <a href=\"#using-vs-code\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h3><p>VS Code is an amazing tool and what I particularly like about it is the variety of features it provides when it comes to navigating through a code base.<\/p>\n<p>The approach we&rsquo;re going to follow is to clone the webpack repo in another custom repo, with the help of <a href=\"https:\/\/git-scm.com\/book\/en\/v2\/Git-Tools-Submodules\" target=\"_blank\" rel=\"noopener\">git submodules<\/a>. We&rsquo;ll do so because it becomes very easy to be up to date with the changes that take place in the webpack repo, as we will see in a moment. I will show the way I&rsquo;m doing things, but feel free to choose whatever approach fits you best.<\/p>\n<p>First, I have created <a href=\"https:\/\/github.com\/Andrei0872\/understanding-webpack\" target=\"_blank\" rel=\"noopener\">this repo<\/a>, named <em>understanding-webpack.<\/em> If you want to follow along, you can set up the repo like this:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-bash\" data-lang=\"bash\"><span style=\"display:flex;\"><span>git clone --recurse-submodules git@github.com:Andrei0872\/understanding-webpack.git\n<\/span><\/span><span style=\"display:flex;\"><span>yarn\n<\/span><\/span><\/code><\/pre><\/div><p>There you will see a directory named <em>examples,<\/em> where each particular example is represented by a directory. In <code>package.json<\/code>, you&rsquo;ll see something like this:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-json\" data-lang=\"json\"><span style=\"display:flex;\"><span><span style=\"color:#e6db74\">&#34;scripts&#34;<\/span><span style=\"color:#960050;background-color:#1e0010\">:<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#f92672\">&#34;understand&#34;<\/span>: <span style=\"color:#e6db74\">&#34;yarn import-order&#34;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#f92672\">&#34;import-order&#34;<\/span>: <span style=\"color:#e6db74\">&#34;webpack --config .\/examples\/import-order\/webpack.config.js&#34;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#f92672\">&#34;create-example&#34;<\/span>: <span style=\"color:#e6db74\">&#34;cd examples &amp;&amp; cp -r dummy-example&#34;<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>  }<span style=\"color:#960050;background-color:#1e0010\">,<\/span>\n<\/span><\/span><\/code><\/pre><\/div><p>The <em>rules<\/em> I decided to follow are these: the <em>main<\/em> command(i.e the command I&rsquo;ll always be running in order try out any example) is <code>yarn understand<\/code>. If you run it now, webpack will use the example from at the <code>examples\/import-order<\/code> path. Each example will get its own script, like <code>import-order<\/code> in the above snippet. When I want to use a different example, all I have to do is to replace <code>import-order<\/code> in <code>&quot;understand&quot;: &quot;yarn import-order&quot;<\/code> with the name of the example.<\/p>\n<p>And now onto the debugging part. There is a <a href=\"https:\/\/github.com\/Andrei0872\/understanding-webpack\/blob\/master\/.vscode\/launch.json\" target=\"_blank\" rel=\"noopener\"><code>.vscode\/launch.json<\/code><\/a> directory which holds the debugging configuration. After pressing <code>F5<\/code>, it should run the <code>yarn understand<\/code> command in a debugging environment, so in order to quickly test it, place a breakpoint in the <code>seal()<\/code> function&rsquo;s body, in <code>Compilation.js<\/code> file(<code>CTRL + P<\/code>, then type <code>webpack\/lib\/Compilation.js<\/code>, then <code>CTRL + SHIFT + O<\/code>, then type <code>seal<\/code>) before starting the debugger.<\/p>\n<p><p class=\"markdown-image\">\n  <img src=\"images\/Screenshot-from-2021-08-25-00-26-08.png\" alt=\"Screenshot from 2021-08-25 00-26-08.png\"  \/>\n<\/p><\/p>\n<p>By the way, the <code>seal<\/code> function encompasses a lot of the steps illustrated in the main diagram, such as: creating the first chunks, building the <code>ChunkGraph<\/code>, generating the runtime code and creating the chunk assets.<\/p>\n<p>So, we&rsquo;ve seen how to debug our own examples. Let&rsquo;s see now how to debug webpack&rsquo;s test or any other script that webpack has defined in its <code>package.json<\/code> file.<\/p>\n<p><strong>A quick side note<\/strong>: If you&rsquo;re running webpack in production mode or, more accurately said, if you include the <em>terser plugin<\/em>, you might have some troubles with the VS Code&rsquo;s built-in debugger, because there is no way to debug <code>worker_threads<\/code> or child processes in VS Code, as far as I&rsquo;m aware. The <code>jest-worker<\/code> package makes use of those and <code>jest-worker<\/code> is used by <code>terser-webpack-plugin<\/code>. For that, I found a very useful tool, called <a href=\"https:\/\/github.com\/GoogleChromeLabs\/ndb\" target=\"_blank\" rel=\"noopener\">ndb<\/a>. After installing it, you can simply <code>cd<\/code> into the <code>webpack<\/code> directory(the git submodule) and type <code>ndb<\/code> to a new window, from which you&rsquo;ll be able to choose which script to run in debugging mode. You can also press breakpoints there, as you&rsquo;d normally do in VS Code.<\/p>\n<p>For instance, I placed a breakpoint in the <code>Chunk.unittest.js<\/code> before telling <em>ndb<\/em> to run the <code>test:unit<\/code> script(found in the bottom left corner):<\/p>\n<p><p class=\"markdown-image\">\n  <img src=\"images\/Screenshot-from-2021-08-25-00-23-02.png\" alt=\"Screenshot from 2021-08-25 00-23-02.png\"  \/>\n<\/p><\/p>\n<p>You can also run specific suite of tests, by using a command similar to this:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-bash\" data-lang=\"bash\"><span style=\"display:flex;\"><span>\/\/ The options are taken from one of the <span style=\"color:#e6db74\">`<\/span>package.json<span style=\"color:#e6db74\">`<\/span> scripts\n<\/span><\/span><span style=\"display:flex;\"><span>\/\/ Simply replace <span style=\"color:#e6db74\">`<\/span>TestCases.template.js<span style=\"color:#e6db74\">`<\/span> with other file name <span style=\"color:#66d9ef\">if<\/span> you want\n<\/span><\/span><span style=\"display:flex;\"><span>\/\/ to debug something <span style=\"color:#66d9ef\">else<\/span>.\n<\/span><\/span><span style=\"display:flex;\"><span>ndb node --max-old-space-size<span style=\"color:#f92672\">=<\/span><span style=\"color:#ae81ff\">4096<\/span> --trace-deprecation node_modules\/jest-cli\/bin\/jest --testMatch <span style=\"color:#e6db74\">&#34;&lt;rootDir&gt;\/test\/TestCases.template.js&#34;<\/span>\n<\/span><\/span><\/code><\/pre><\/div><p>One problem that <code>ndb<\/code> solves is to allow you to use the debugger on files that are executed on a worker thread or on a different process than the original which started the debugging process. So, if you want to debug the <em>terser&rsquo;s<\/em> minifying process on your custom example, you can use <code>ndb yarn understand<\/code>(from the repo&rsquo;s root directory):<\/p>\n<p><p class=\"markdown-image\">\n  <img src=\"images\/Screenshot-from-2021-08-25-14-48-41.png\" alt=\"Screenshot from 2021-08-25 14-48-41.png\"  \/>\n<\/p><\/p>\n<p>The file can be found at <code>webpack\/node_modules\/terser-webpack-plugin\/dist\/minify.js<\/code>. If you try debugging in VS Code, you should notice that the breakpoint won&rsquo;t be hit. With <code>ndb<\/code>, however, it works.<\/p>\n<p>If you want to explore the bundling process from the beginning, you can add a breakpoint in the <code>createCompiler<\/code> function, in the <code>webpack\/lib\/webpack.js<\/code> file.<\/p>\n<p><p class=\"markdown-image\">\n  <img src=\"images\/Screenshot-from-2021-08-25-14-32-42.png\" alt=\"Screenshot from 2021-08-25 14-32-42.png\"  \/>\n<\/p><\/p>\n<p>At this point, you can also inspect the default configuration values.<\/p>\n<p>So, my recommendation would be to use <code>ndb<\/code> whenever you want to debug files that are run with the help of <code>worker_threads<\/code> or run on a different process than the one which you started the debugging process with.<\/p>\n<h3 id=\"a-few-tricks-to-easily-navigate-in-webpacks-or-any-codebase\">\n  <span>\n  A few tricks to easily navigate in webpack&rsquo;s (or any) codebase\n  <\/span>\n  <a href=\"#a-few-tricks-to-easily-navigate-in-webpacks-or-any-codebase\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h3><p><em>Note: this assumes the VS Code editor is used.<\/em><\/p>\n<ul>\n<li>use <code>CTRL + SHIFT + F12<\/code> to see all the places in the repo where a certain variable\/entity\/function has been used:<\/li>\n<\/ul>\n<p><p class=\"markdown-image\">\n  <img src=\"images\/Screenshot-from-2021-08-25-15-00-47.png\" alt=\"Screenshot from 2021-08-25 15-00-47.png\"  \/>\n<\/p><\/p>\n<ul>\n<li>use <code>CTRL + SHIFT + \\<\/code> to go to the matching parenthesis<\/li>\n<li>use <code>ALT + SHIFT + \u00a0H<\/code> to see the <strong>call hierarchy<\/strong><\/li>\n<\/ul>\n<p><p class=\"markdown-image\">\n  <img src=\"images\/Screenshot-from-2021-08-25-15-04-35.png\" alt=\"Screenshot from 2021-08-25 15-04-35.png\"  \/>\n<\/p><\/p>\n<p>In the above screenshot, you can see what causes the <code>setResolvedModule<\/code> to be called.<\/p>\n<ul>\n<li>to determine which plugins have added custom functionality to the hooks provided by webpack, you can do a global search(<code>CTRL + SHIFT + F<\/code>) and type <code>.hooks.nameOfTheHook.tap<\/code>(the way you add custom functionality to a hook is by using the <code>tap\/tapAsync<\/code> method):<\/li>\n<\/ul>\n<p><p class=\"markdown-image\">\n  <img src=\"images\/Screenshot-from-2021-08-25-15-10-32.png\" alt=\"Screenshot from 2021-08-25 15-10-32.png\"  \/>\n<\/p><\/p>\n<p>In the left panel you can see which plugins have added new logic to the built-in <code>optimizeChunks<\/code> hook.<\/p>\n<p>Moreover, if you&rsquo;re using the debugger, quickly inspect the <code>taps<\/code> property of a hook to see the sources from where functionality has been added:<\/p>\n<p><p class=\"markdown-image\">\n  <img src=\"images\/Screenshot-from-2021-08-25-15-15-04.png\" alt=\"Screenshot from 2021-08-25 15-15-04.png\"  \/>\n<\/p><\/p>\n<h3 id=\"using-stackblitz\">\n  <span>\n  Using StackBlitz\n  <\/span>\n  <a href=\"#using-stackblitz\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h3><p><a href=\"https:\/\/stackblitz.com\/\" target=\"_blank\" rel=\"noopener\">StackBlitz<\/a> is another great tool that we&rsquo;re lucky to have as developers. When using StackBlitz, you basically no longer have to leave the browser and you can do exactly what&rsquo;s been explained in the the <em>Using VS Code<\/em> section. Moreover, the <code>ndb<\/code> behavior is already built in StackBlitz - so, no need for an additional tool!<\/p>\n<p>I have created a StackBlitz project called <a href=\"https:\/\/stackblitz.com\/edit\/node-cazzv3?file=webpack.config.js\" target=\"_blank\" rel=\"noopener\"><code>webpack-base<\/code><\/a> and it contains a basic setup and it can be a very good starting point when creating other demos. Whenever I want to quickly explore some webpack feature, I simply open this project, fork it and I&rsquo;m good to go!<\/p>\n<p>I also made <a href=\"https:\/\/www.youtube.com\/watch?v=9s-t3uECOic\" target=\"_blank\" rel=\"noopener\">a video about it<\/a>. Assuming we want to start exploring the bundling process from the point where the compiler is created, here are the necessary steps to do that(make sure to fork the project first):<\/p>\n<ul>\n<li>run <code>code node_modules\/webpack\/lib\/webpack.js<\/code> in the terminal<\/li>\n<li>go to line 135(<code>CTRL + G<\/code> - same as in VS Code!) or search for the place where the <code>create<\/code> function is invoked(<code>CTRL + SHIFT + P<\/code> could help)<\/li>\n<li>type the <code>debugger;<\/code> keyword<\/li>\n<li>open the DevTools<\/li>\n<li>run the <code>npm run build<\/code> script in terminal<\/li>\n<\/ul>\n<p><p class=\"markdown-image\">\n  <img src=\"images\/Screenshot-from-2021-09-09-21-01-46.png\" alt=\"Screenshot from 2021-09-09 21-01-46.png\"  \/>\n<\/p><\/p>\n<p>We&rsquo;ve used the <code>debugger;<\/code> keyword so that the file would appear much easier in the <code>Sources<\/code> tab. Sometimes it can be difficult to find it with <code>CTRL + P<\/code>. From this point, you can debug as you would normally do: click on line numbers to place breakpoints, you can add conditional breakpoints, step into etc.<\/p>\n<blockquote>\n<p>You can apply the same process for <strong>every node script.<\/strong><\/p>\n<\/blockquote>\n<h2 id=\"conclusion\">\n  <span>\n  Conclusion\n  <\/span>\n  <a href=\"#conclusion\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><p>In this article I&rsquo;ve tried to include, without redundant details, as much information as needed in order for you to see webpack from a different perspective. It is a complex (and fascinating) tool and this write-up aimed to break it in smaller and digestible parts.<\/p>\n<p><strong>Thanks for reading!<\/strong><\/p>\n<p><em>The diagrams have been made with <a href=\"https:\/\/excalidraw.com\/\" target=\"_blank\" rel=\"noopener\">Excalidraw<\/a>.<\/em><\/p>\n<p><em>Special thanks <a href=\"https:\/\/twitter.com\/maxkoretskyi\" target=\"_blank\" rel=\"noopener\">Max Koretskyi<\/a> for reviewing this article and for providing extremely valuable feedback.<\/em><\/p>\n"},{"title":"Angular Router: empty paths, named outlets and a fix that came with Angular 11 ","link":"https:\/\/andreigatej.dev\/blog\/angular-router-empty-paths-named-outlets\/","pubDate":"Tue, 29 Jun 2021 00:00:00 +0000","guid":"https:\/\/andreigatej.dev\/blog\/angular-router-empty-paths-named-outlets\/","description":"<h2 id=\"introduction\">\n  <span>\n  Introduction\n  <\/span>\n  <a href=\"#introduction\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><p>In this article, we are going to highlight the importance of a fix that came with the 11th version of Angular Router. We will do so by examining a scenario where the lack of that fix prevents an intuitive solution from working, as well as understanding why the fix in question solves the problem.<br>\nar Router. Although we will make use of some <em>advanced<\/em> concepts like <code>UrlTree<\/code>, <code>UrlSegmentGroup<\/code>, they will be briefly described before being applied.<\/p>\n<p><em>This article has been inspired by <a href=\"https:\/\/stackoverflow.com\/questions\/68109583\/passing-parameters-in-named-outlets-is-not-working\/68137662#68137662\" target=\"_blank\" rel=\"noopener\">this Stack Overflow question<\/a>.<\/em><\/p>\n<p>Throughout the article we will not be using the example from the aforementioned Stack Overflow question. Instead, it will be a simpler example, so that it can better illustrate the problem we are trying to solve. Before going any further, we must be aware of how Angular Router resolves routes transitions. For that, we&rsquo;ll have to introduce the notion of <code>UrlTree<\/code>.<\/p>\n<p>Given a URL string, it will be converted into an equivalent <code>UrlTree<\/code>, which Angular Router will further use to determine whether a configuration exists or not for that route. It can achieve that by traversing the given <code>Routes<\/code> configuration array and the <code>UrlTree<\/code> simultaneously. This is how the <code>UrlTree<\/code> structure looks like:<\/p>\n<pre><code>export class UrlTree {\n\/* ... *\/\nconstructor(\n  \/** The root segment group of the URL tree *\/\n  public root: UrlSegmentGroup,\n  \/** The query params of the URL *\/\n  public queryParams: Params,\n  \/** The fragment of the URL *\/\n  public fragment: string|null) {}\n}\n<\/code><\/pre>\n<p>Enter fullscreen mode Exit fullscreen mode<\/p>\n<p>as you can probably see, it already resembles a URL, since it has properties like <code>queryParams<\/code> and <code>fragment<\/code>. It looks like only the <strong>segments<\/strong> of a URL are missing. For that, there is <code>UrlSegmentGroup<\/code>, which looks as follows:<\/p>\n<pre><code>export class UrlSegmentGroup {\n  \/* ... *\/\n  parent: UrlSegmentGroup|null = null;\n\n  constructor(\n    \/** The URL segments of this group. See `UrlSegment` for more information *\/\n    public segments: UrlSegment[],\n    \/** The list of children of this group *\/\n    public children: {[key: string]: UrlSegmentGroup}) {\n    forEach(children, (v: any, k: any) =&gt; v.parent = this);\n  }\n}\n<\/code><\/pre>\n<p>Enter fullscreen mode Exit fullscreen mode<\/p>\n<p>and with this we can understand why it&rsquo;s called a <code>UrlTree<\/code>, because a URL can apparently be seen as a <strong>tree of segments<\/strong>. Now it comes the genuine question: why would you need a tree-like structure to represent the segments of a URL? The answer is because Angular Router also supports <strong>named outlets<\/strong> and in fact, every property from the <code>children<\/code> object form above represents a named outlet. It should also be mentioned that when no outlet is specified, the <strong>primary outlet<\/strong> is used by default.<\/p>\n<p>A <code>UrlSegment<\/code> is used to represent a URL segment and for each segment it keeps track of the <strong>name<\/strong> and the <strong>segment parameters<\/strong>.<\/p>\n<p>Let&rsquo;s see an example: given the URL <code>'foo\/123\/(a\/\/named:b)'<\/code>(where <code>named<\/code> refers to a named outlet called <code>named<\/code>), its equivalent <code>UrlTree<\/code> will be:<\/p>\n<pre><code>{\n  segments: [], \/\/ The root UrlSegmentGroup never has any segments\n  children: {\n    primary: {\n      segments: [{ path: 'foo', parameters: {} }, { path: '123', parameters: {} }],\n      children: {\n        primary: { segments: [{ path: 'a', parameters: {} }], children: {} },\n        named: { segments: [{ path: 'b', parameters: {} }], children: {} },\n      },\n    },\n  },\n}\n<\/code><\/pre>\n<p>Enter fullscreen mode Exit fullscreen mode<\/p>\n<p>A structure like the one from above is then used when traversing the <code>Routes<\/code> configuration array. A configuration that would match the given URL would be this one:<\/p>\n<pre><code>{\n  \/\/ app-routing.module.ts\n  {\n    path: 'foo\/:id',\n    loadChildren: () =&gt; import('.\/foo\/foo.module').then(m =&gt; m.FooModule)\n  },\n\u200b\n  \/\/ foo.module.ts\n  {\n    path: 'a',\n    component: AComponent,\n  },\n  {\n    path: 'b',\n    component: BComponent,\n    outlet: 'named',\n  },\n}\n<\/code><\/pre>\n<p>Enter fullscreen mode Exit fullscreen mode<\/p>\n<p><em>You can try out the above example <a href=\"https:\/\/stackblitz.com\/edit\/routing-base-url-parser?file=src%2Fapp%2Fapp.module.ts\" target=\"_blank\" rel=\"noopener\">here<\/a>.<\/em><\/p>\n<p>Now that we grasped the fundamentals of <code>UrlTree<\/code>, it&rsquo;s time to see the problem we are trying to solve.<\/p>\n<p><em>If you&rsquo;d like to read more about <code>UrlTree<\/code>, I&rsquo;d recommend having a look at <a href=\"https:\/\/andreigatej.dev\/blog\/angular-router-urlree\" target=\"_blank\" rel=\"noopener\">Angular Router: Getting to know UrlTree, ActivatedRouteSnapshot and ActivatedRoute<\/a>.<\/em><\/p>\n<h2 id=\"the-problemthe-problem\">\n  <span>\n  <a href=\"#the-problem\"><\/a>The problem\n  <\/span>\n  <a href=\"#the-problemthe-problem\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><p>Suppose you are given a configuration that looks like this:<\/p>\n<pre><code>const routes: Routes = [\n  {\n    path: '',\n    component: FooContainer1,\n    children: [\n      {\n        path: '',\n        component: FooContainer2,\n        children: [\n          {\n            path: ':id',\n            component: FooComponent1,\n            outlet: 'test'\n          },\n          {\n            path: '',\n            pathMatch: 'full',\n            component: DummyComponent1\n          }\n        ]\n      }\n    ]\n  }\n];\n<\/code><\/pre>\n<p>Enter fullscreen mode Exit fullscreen mode<\/p>\n<p>Can you think of a URL that would activate the <code>FooComponent1<\/code> component?<\/p>\n<p>If your answer is<\/p>\n<pre><code>&lt;button [routerLink]=&quot;['\/', { outlets: { test: [123] } }]&quot;&gt;&lt;!-- ... --&gt;&lt;\/button&gt;\n<\/code><\/pre>\n<p>Enter fullscreen mode Exit fullscreen mode<\/p>\n<p>then, whether you are correct or not depends on which version of Angular you&rsquo;re using. In both cases, the <code>UrlTree<\/code> of the above is:<\/p>\n<pre><code>{\n  fragment: undefined\n  queryParams: {}\n  root: {\n    children:\n      test: {\n        children: {}\n        segments: [{ path: '123' }]\n      }\n    segments: []\n  }\n}\n<\/code><\/pre>\n<p>Enter fullscreen mode Exit fullscreen mode<\/p>\n<p>In Angular versions earlier than 11, the above solution won&rsquo;t work and we will have to find another approach. In Angular 11 this is fixed. Let&rsquo;s see each case in detail.<\/p>\n<h2 id=\"the-process-of-matching-raw-routes-endraw-with-raw-urlsegmentgroup-endraw-sthe-process-of-matching-routes-with-urlsegmentgroups\">\n  <span>\n  <a href=\"#the-process-of-matching-raw-routes-endraw-with-raw-urlsegmentgroup-endraw-s\"><\/a>The process of matching <code>Routes<\/code> with <code>UrlSegmentGroup<\/code>s\n  <\/span>\n  <a href=\"#the-process-of-matching-raw-routes-endraw-with-raw-urlsegmentgroup-endraw-sthe-process-of-matching-routes-with-urlsegmentgroups\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><p>It is now worth talking about the <em>matching process<\/em> between <code>Routes<\/code> configuration and a <code>UrlSegmentGroup<\/code>.<\/p>\n<p>The number of segments(delimited by <code>\/<\/code>) in the <code>Route<\/code>&rsquo;s <code>path<\/code> property does not have to be equal to the number of <code>UrlSegmentGroup.segments<\/code>. In order for a <code>Route<\/code> to be matched, the numbers of segments in the <code>path<\/code> property must be less than or equal to the length of <code>UrlSegmentGroup.segments<\/code>. If the previous condition is met, the some of the <code>UrlSegmentGroup.segments<\/code> segments are said to be <em>consumed<\/em>.<\/p>\n<p>The <a href=\"https:\/\/github.com\/angular\/angular\/blob\/bbeac0727b8f267a47aba1ff1bcfc8cc5ca15b61\/packages\/router\/src\/recognize.ts#L185-L191\" target=\"_blank\" rel=\"noopener\">same logic<\/a> applies in case of <code>{ path: '', }<\/code>:<\/p>\n<pre><code>if (route.path === '') {\n  if (route.pathMatch === 'full' &amp;&amp; (segmentGroup.hasChildren() || segments.length &gt; 0)) {\n    throw new NoMatch();\n  }\n\n  return {consumedSegments: [], lastChild: 0, parameters: {}};\n}\n<\/code><\/pre>\n<p>Enter fullscreen mode Exit fullscreen mode<\/p>\n<p>It was necessary to briefly introduce this notion because, based on the <em>consumed segments<\/em>, there will be 3 cases:<\/p>\n<ol>\n<li>All the <code>UrlSegmentGroup.segments<\/code> are consumed <strong>and<\/strong> <code>UrlSegmentGroup.children<\/code> is not empty:<\/li>\n<\/ol>\n<p>An example of this is even the one we have seen at the beginning of this article:<\/p>\n<p><p class=\"markdown-image\">\n  <img src=\"images\/case-1.png\" alt=\"image content\"  \/>\n<\/p><\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span>    <span style=\"color:#75715e\">\/\/ The `UrlTree`\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>    {\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#a6e22e\">segments<\/span><span style=\"color:#f92672\">:<\/span> [], <span style=\"color:#75715e\">\/\/ The root UrlSegmentGroup never has any segments\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>      <span style=\"color:#a6e22e\">children<\/span><span style=\"color:#f92672\">:<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#a6e22e\">primary<\/span><span style=\"color:#f92672\">:<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>          <span style=\"color:#a6e22e\">segments<\/span><span style=\"color:#f92672\">:<\/span> [{ <span style=\"color:#a6e22e\">path<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;foo&#39;<\/span>, <span style=\"color:#a6e22e\">parameters<\/span><span style=\"color:#f92672\">:<\/span> {} }, { <span style=\"color:#a6e22e\">path<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;123&#39;<\/span>, <span style=\"color:#a6e22e\">parameters<\/span><span style=\"color:#f92672\">:<\/span> {} }],\n<\/span><\/span><span style=\"display:flex;\"><span>          <span style=\"color:#a6e22e\">children<\/span><span style=\"color:#f92672\">:<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>            <span style=\"color:#a6e22e\">primary<\/span><span style=\"color:#f92672\">:<\/span> { <span style=\"color:#a6e22e\">segments<\/span><span style=\"color:#f92672\">:<\/span> [{ <span style=\"color:#a6e22e\">path<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;a&#39;<\/span>, <span style=\"color:#a6e22e\">parameters<\/span><span style=\"color:#f92672\">:<\/span> {} }], <span style=\"color:#a6e22e\">children<\/span><span style=\"color:#f92672\">:<\/span> {} },\n<\/span><\/span><span style=\"display:flex;\"><span>            <span style=\"color:#a6e22e\">named<\/span><span style=\"color:#f92672\">:<\/span> { <span style=\"color:#a6e22e\">segments<\/span><span style=\"color:#f92672\">:<\/span> [{ <span style=\"color:#a6e22e\">path<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;b&#39;<\/span>, <span style=\"color:#a6e22e\">parameters<\/span><span style=\"color:#f92672\">:<\/span> {} }], <span style=\"color:#a6e22e\">children<\/span><span style=\"color:#f92672\">:<\/span> {} },\n<\/span><\/span><span style=\"display:flex;\"><span>          },\n<\/span><\/span><span style=\"display:flex;\"><span>        },\n<\/span><\/span><span style=\"display:flex;\"><span>      },\n<\/span><\/span><span style=\"display:flex;\"><span>    }\n<\/span><\/span><span style=\"display:flex;\"><span>    \n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#75715e\">\/\/ The configuration\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>    {\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#75715e\">\/\/ app-routing.module.ts\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>      {\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#a6e22e\">path<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;foo\/:id&#39;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#a6e22e\">loadChildren<\/span><span style=\"color:#f92672\">:<\/span> () <span style=\"color:#f92672\">=&gt;<\/span> <span style=\"color:#66d9ef\">import<\/span>(<span style=\"color:#e6db74\">&#39;.\/foo\/foo.module&#39;<\/span>).<span style=\"color:#a6e22e\">then<\/span>(<span style=\"color:#a6e22e\">m<\/span> <span style=\"color:#f92672\">=&gt;<\/span> <span style=\"color:#a6e22e\">m<\/span>.<span style=\"color:#a6e22e\">FooModule<\/span>)\n<\/span><\/span><span style=\"display:flex;\"><span>      },\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#960050;background-color:#1e0010\">\u200b<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#75715e\">\/\/ foo.module.ts\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>      {\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#a6e22e\">path<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;a&#39;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#a6e22e\">component<\/span>: <span style=\"color:#66d9ef\">AComponent<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>      },\n<\/span><\/span><span style=\"display:flex;\"><span>      {\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#a6e22e\">path<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;b&#39;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#a6e22e\">component<\/span>: <span style=\"color:#66d9ef\">BComponent<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#a6e22e\">outlet<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;named&#39;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>      },\n<\/span><\/span><span style=\"display:flex;\"><span>    }\n<\/span><\/span><\/code><\/pre><\/div><p>Enter fullscreen mode Exit fullscreen mode<\/p>\n<p>Recall that <code>UrlSegmentGroup.children<\/code>&rsquo;s values are named outlets and their segments.<\/p>\n<ol>\n<li>\n<p>All the <code>UrlSegmentGroup.segments<\/code> are consumed <strong>and<\/strong> <code>UrlSegmentGroup.children<\/code> is empty:<\/p>\n<p>const routes: Routes = [\n{\npath: &lsquo;foo\/bar&rsquo;\n}\n];<\/p>\n<\/li>\n<\/ol>\n<p>Enter fullscreen mode Exit fullscreen mode<\/p>\n<p>and the URL is <code>foo\/bar<\/code>.<\/p>\n<p>Here&rsquo;s how the <code>UrlTree<\/code> for <code>foo\/bar<\/code> looks like:<\/p>\n<pre><code>{\n  fragment: null,\n  queryParams: {},\n  root: {\n    children: {\n      primary: {\n        \/\/ It is empty\n        children: {},\n        \/\/ Both will be *consumed*\n        segments: [{ path: 'foo', parameters: {} }, { path: 'bar', parameters: {} }]\n      }\n    },\n    segments: [],\n  }\n}\n<\/code><\/pre>\n<p>Enter fullscreen mode Exit fullscreen mode<\/p>\n<ol>\n<li>Not all of the <code>UrlSegmentGroup.segments<\/code> have been consumed:<\/li>\n<\/ol>\n<p>This is the point where Angular 11 and Angular &lt;11 are different.<\/p>\n<p>In this case, only a few parts of <code>UrlSegmentGroup.segments<\/code> are consumed. In this case, if the current <code>Route<\/code> object has either a <code>children<\/code> property or <code>loadChildren<\/code>, it will traverse the array found in one of these properties.<\/p>\n<p>The problem here with version earlier than 11 is that when traversing the new inner <code>Routes<\/code> configuration array, it will <strong>not<\/strong> take into account the current outlet name. Recall that an outlet&rsquo;s name is a property in the <code>UrlSegmentGroup.children<\/code> object.<\/p>\n<p>Coming back to our initial example:<\/p>\n<pre><code>const routes: Routes = [\n  {\n    path: '',\n    component: FooContainer1,\n    children: [\n      {\n        path: '',\n        component: FooContainer2,\n        children: [\n          {\n            path: ':id',\n            component: FooComponent1,\n            outlet: 'test'\n          },\n          {\n            path: '',\n            pathMatch: 'full',\n            component: DummyComponent1\n          }\n        ]\n      }\n    ]\n  }\n];\n<\/code><\/pre>\n<p>Enter fullscreen mode Exit fullscreen mode<\/p>\n<p>and<\/p>\n<pre><code>&lt;button [routerLink]=&quot;['\/', { outlets: { test: [123] } }]&quot;&gt;&lt;!-- ... --&gt;&lt;\/button&gt;\n<\/code><\/pre>\n<p>Enter fullscreen mode Exit fullscreen mode<\/p>\n<p>Because the <code>path<\/code> is <code>''<\/code>, the <code>UrlSegmentGroup.segments<\/code> <strong>won&rsquo;t be consumed<\/strong>(<a href=\"https:\/\/github.com\/angular\/angular\/blob\/bbeac0727b8f267a47aba1ff1bcfc8cc5ca15b61\/packages\/router\/src\/recognize.ts#L185-L191\" target=\"_blank\" rel=\"noopener\">here&rsquo;s why<\/a>). The way this is handled in earlier versions is to <strong>always<\/strong> use the <strong>primary outlet name<\/strong>, although the current outlet name might be different. Since the <code>UrlTree<\/code> generated by the above <code>RouterLink<\/code> looks like this:<\/p>\n<pre><code>{\n  fragment: undefined\n  queryParams: {}\n  root: {\n    children:\n      \/\/ No `primary` outlet here, only `test`.\n      test: {\n        children: {}\n        segments: [{ path: '123' }]\n      }\n    segments: []\n  }\n}\n<\/code><\/pre>\n<p>Enter fullscreen mode Exit fullscreen mode<\/p>\n<p>there won&rsquo;t be any match and the navigation will fail.<\/p>\n<p><em><a href=\"https:\/\/github.com\/angular\/angular\/blob\/8.2.14\/packages\/router\/src\/apply_redirects.ts#L279-L281\" target=\"_blank\" rel=\"noopener\">This is the current implementation that prevents the above approach from working<\/a>.<\/em><\/p>\n<p>And <a href=\"https:\/\/stackblitz.com\/edit\/angular-8-app-example-qeznoh?file=src%2Fapp%2Fapp.component.html\" target=\"_blank\" rel=\"noopener\">here<\/a> is a StackBlitz app with our example and there you can see the navigation fails.<\/p>\n<h2 id=\"the-fix-that-came-with-angular-11the-fix-that-came-with-angular-11\">\n  <span>\n  <a href=\"#the-fix-that-came-with-angular-11\"><\/a>The fix that came with Angular 11\n  <\/span>\n  <a href=\"#the-fix-that-came-with-angular-11the-fix-that-came-with-angular-11\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><p>With this version, the exact problem that we had before(at the third case) is fixed. The way this is done is by using the current outlet name when in the third scenario occurs.<\/p>\n<p><a href=\"https:\/\/stackblitz.com\/edit\/angular-ivy-supznj?file=src%2Fapp%2Fapp.module.ts\" target=\"_blank\" rel=\"noopener\">Here<\/a> is the our initial problem, but in Angular 11. As you can see, it&rsquo;s working.<\/p>\n<p>And <a href=\"https:\/\/github.com\/angular\/angular\/blob\/master\/packages\/router\/src\/apply_redirects.ts#L321-L322\" target=\"_blank\" rel=\"noopener\">here<\/a>&rsquo;s the relevant source code that fixed the problem:<\/p>\n<pre><code>\/* ... *\/\n\/\/ `childConfig` in this case refers to the content of `children` property.\nconst matchedOnOutlet = getOutlet(route) === outlet;\nconst expanded$ = this.expandSegment(\n    childModule, segmentGroup, childConfig, slicedSegments,\n    matchedOnOutlet ? PRIMARY_OUTLET : outlet, true);\n<\/code><\/pre>\n<p>Enter fullscreen mode Exit fullscreen mode<\/p>\n<p>Let&rsquo;s briefly visualize the process:<\/p>\n<p><p class=\"markdown-image\">\n  <img src=\"images\/case-3.png\" alt=\"image content\"  \/>\n<\/p><\/p>\n<p>Because the outlet name won&rsquo;t always be <code>primary<\/code> and since all the paths until <code>FooComponent1<\/code> are <code>''<\/code>, the first <code>children<\/code> array will be traversed(denoted by<code>(1)<\/code>), then the second <code>children<\/code> array(denoted by <code>(2)<\/code>) and there it will finally find the match.<\/p>\n<h2 id=\"conclusionconclusion\">\n  <span>\n  <a href=\"#conclusion\"><\/a>Conclusion\n  <\/span>\n  <a href=\"#conclusionconclusion\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><p>Although the fix was a small one, it had a big impact. I had stumbled across a few bugs in the past which were caused by this, so personally I&rsquo;m glad they eventually found a solution.<\/p>\n<p>Thanks for reading!<\/p>\n<p><em>Credit goes to the Stack Overflow user Dina Flies, who posted the question.<\/em><\/p>\n<p><em>The diagrams were made with <a href=\"https:\/\/excalidraw.com\/\" target=\"_blank\" rel=\"noopener\">Excalidraw<\/a>.<\/em><\/p>\n"},{"title":"RxJS: Why memory leaks occur when using a Subject","link":"https:\/\/andreigatej.dev\/blog\/rxjs-why-memory-leaks-occur-when-using-a-subject\/","pubDate":"Sat, 13 Feb 2021 00:00:00 +0000","guid":"https:\/\/andreigatej.dev\/blog\/rxjs-why-memory-leaks-occur-when-using-a-subject\/","description":"<p><em>This article has been published on <a href=\"https:\/\/indepth.dev\/posts\/1433\/rxjs-why-memory-leaks-occur-when-using-a-subject\" target=\"_blank\" rel=\"noopener\">indepth.dev<\/a>.<\/em><\/p>\n<h2 id=\"introduction\">\n  <span>\n  Introduction\n  <\/span>\n  <a href=\"#introduction\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><p>It&rsquo;s not uncommon to see the words <em>unsubscribe<\/em>, <em>memory leaks<\/em>, <em>subject<\/em> in the same phrase when reading upon RxJS-related materials. In this article, we&rsquo;re going to tackle this fact and by the end of it you should gain a better insight as to why memory leaks occur and why a simple <code>unsubscribe()<\/code> solves the problem. Although the reader should have some familiarity with RxJS, the necessary concepts will be clarified as things move on. If you want to learn more about RxJS subjects, <a href=\"https:\/\/indepth.dev\/reference\/rxjs\/subjects\" target=\"_blank\" rel=\"noopener\">start here<\/a>.<\/p>\n<p><em>This article has been inspired by <a href=\"https:\/\/stackoverflow.com\/questions\/63257763\/do-subscriptions-to-rxjs-subjects-cause-memory-leaks-if-not-unsubscribed-when-th\/63258734#63258734\" target=\"_blank\" rel=\"noopener\">this Stack Overflow answer<\/a>.<\/em><\/p>\n<h2 id=\"understanding-the-problem\">\n  <span>\n  Understanding the problem\n  <\/span>\n  <a href=\"#understanding-the-problem\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><p>Although the RxJS library can be used on its own or in conjunction with any library\/framework, we&rsquo;ll discuss the problem in the context of Angular, just for convenience. This shouldn&rsquo;t be a problem, since the concepts are applicable in any case.<\/p>\n<p>But first, let\u2019s demonstrate a memory leak in pure RxJS and we will then expand upon that:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">source<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">new<\/span> <span style=\"color:#a6e22e\">Subject<\/span>();\n<\/span><\/span><span style=\"display:flex;\"><span> \n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">let<\/span> <span style=\"color:#a6e22e\">s<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">source<\/span>.<span style=\"color:#a6e22e\">subscribe<\/span>(<span style=\"color:#a6e22e\">v<\/span> <span style=\"color:#f92672\">=&gt;<\/span> <span style=\"color:#a6e22e\">console<\/span>.<span style=\"color:#a6e22e\">log<\/span>(<span style=\"color:#e6db74\">&#34;subscriber 1: &#34;<\/span>, <span style=\"color:#a6e22e\">v<\/span>));\n<\/span><\/span><span style=\"display:flex;\"><span> \n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">source<\/span>.<span style=\"color:#a6e22e\">next<\/span>(<span style=\"color:#e6db74\">&#34;1&#34;<\/span>); <span style=\"color:#75715e\">\/\/ logs: subscriber 1: 1\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span> \n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ this won&#39;t do anything\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span><span style=\"color:#a6e22e\">s<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">null<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span> \n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ notice we didn\u2019t unsubscribe before\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span><span style=\"color:#a6e22e\">s<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">source<\/span>.<span style=\"color:#a6e22e\">subscribe<\/span>(<span style=\"color:#a6e22e\">v<\/span> <span style=\"color:#f92672\">=&gt;<\/span> <span style=\"color:#a6e22e\">console<\/span>.<span style=\"color:#a6e22e\">log<\/span>(<span style=\"color:#e6db74\">&#34;subscriber 2: &#34;<\/span>, <span style=\"color:#a6e22e\">v<\/span>));\n<\/span><\/span><span style=\"display:flex;\"><span> \n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">source<\/span>.<span style=\"color:#a6e22e\">next<\/span>(<span style=\"color:#e6db74\">&#34;2&#34;<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ logs:\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ subscriber 1: 2 \/\/ !!! - this shouldn&#39;t be here\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ subscriber 2: 2\n<\/span><\/span><\/span><\/code><\/pre><\/div><p><em>A StackBlitz app for the above snippet can be found <a href=\"https:\/\/stackblitz.com\/edit\/rxjs-memory-leak-example?file=index.ts\" target=\"_blank\" rel=\"noopener\">here<\/a>.<\/em><\/p>\n<p>In Angular, a common pattern is to inject services into components and subscribe to the observable properties exposed by those services:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">class<\/span> <span style=\"color:#a6e22e\">Service<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span> <span style=\"color:#66d9ef\">private<\/span> <span style=\"color:#a6e22e\">usersSrc<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">new<\/span> <span style=\"color:#a6e22e\">Subject<\/span>();\n<\/span><\/span><span style=\"display:flex;\"><span> <span style=\"color:#a6e22e\">users$<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">usersSrc<\/span>.<span style=\"color:#a6e22e\">asObservable<\/span>();\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p>Such services can be consumed like this:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">class<\/span> <span style=\"color:#a6e22e\">FooComponent<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span> <span style=\"color:#66d9ef\">constructor<\/span> (<span style=\"color:#66d9ef\">private<\/span> <span style=\"color:#a6e22e\">service<\/span>: <span style=\"color:#66d9ef\">Service<\/span>) { }\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">ngOnInit<\/span> () {\n<\/span><\/span><span style=\"display:flex;\"><span>   <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">subscription<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">service<\/span>.<span style=\"color:#a6e22e\">users$<\/span>.<span style=\"color:#a6e22e\">subscribe<\/span>(<span style=\"color:#a6e22e\">nextCb<\/span>, <span style=\"color:#a6e22e\">errorCb<\/span>, <span style=\"color:#a6e22e\">completeCb<\/span>)\n<\/span><\/span><span style=\"display:flex;\"><span> }\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p>As you know, a <code>Subject<\/code> is a special type of <code>Observable<\/code> and comes with some very interesting features. The most relevant for us is the fact that it can be subscribed to and it maintains a list of subscribers. The <em>subscription process<\/em> deserves an article on its own, but for now it&rsquo;s important to understand that a subject, when its <code>subject.next()<\/code> method is invoked, it will send the value to all of the registered subscribers. Because a subscriber is registered when the <code>subscribe(nextCb, ...)<\/code> method is invoked, the value from the source will be available in the <code>nextCb<\/code>.<\/p>\n<p>In other words, all callbacks are kept in the subject.<\/p>\n<p>Now, when the component is destroyed(e.g due to navigating to another route), if we don&rsquo;t call <code>this.subscription.unsubscribe()<\/code>, that subscriber will still be part of that subscribers list. What <code>unsubscribe<\/code> really does is to remove that subscriber from that list. This is important, because the next time the component is created and that <code>ngOnInit<\/code> is called, a new subscriber will be added to the subscribers list, but the old one would still be there if <code>this.subscription.unsubscribe()<\/code> is not called.<\/p>\n<p>Here is a simplified version of the case when a memory leak occurs:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ the Subject used in the service\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span><span style=\"color:#66d9ef\">let<\/span> <span style=\"color:#a6e22e\">src<\/span> <span style=\"color:#f92672\">=<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span> <span style=\"color:#a6e22e\">subscribers<\/span><span style=\"color:#f92672\">:<\/span> [],\n<\/span><\/span><span style=\"display:flex;\"><span> \n<\/span><\/span><span style=\"display:flex;\"><span> <span style=\"color:#a6e22e\">addSubscriber<\/span>(<span style=\"color:#a6e22e\">cb<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>   <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">subscribers<\/span>.<span style=\"color:#a6e22e\">push<\/span>(<span style=\"color:#a6e22e\">cb<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>   <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">subscribers<\/span>.<span style=\"color:#a6e22e\">length<\/span> <span style=\"color:#f92672\">-<\/span> <span style=\"color:#ae81ff\">1<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span> },\n<\/span><\/span><span style=\"display:flex;\"><span> \n<\/span><\/span><span style=\"display:flex;\"><span> <span style=\"color:#a6e22e\">removeSubscriber<\/span>(<span style=\"color:#a6e22e\">idx<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>   <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">subscribers<\/span>.<span style=\"color:#a6e22e\">splice<\/span>(<span style=\"color:#a6e22e\">idx<\/span>, <span style=\"color:#ae81ff\">1<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span> },\n<\/span><\/span><span style=\"display:flex;\"><span> <span style=\"color:#a6e22e\">next<\/span>(<span style=\"color:#a6e22e\">data<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>   <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">subscribers<\/span>.<span style=\"color:#a6e22e\">forEach<\/span>(<span style=\"color:#a6e22e\">cb<\/span> <span style=\"color:#f92672\">=&gt;<\/span> <span style=\"color:#a6e22e\">cb<\/span>(<span style=\"color:#a6e22e\">data<\/span>));\n<\/span><\/span><span style=\"display:flex;\"><span> }\n<\/span><\/span><span style=\"display:flex;\"><span>};\n<\/span><\/span><\/code><\/pre><\/div><p>And this is how a simplified version of a component would look like:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ the component\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span><span style=\"color:#66d9ef\">class<\/span> <span style=\"color:#a6e22e\">Foo<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span> <span style=\"color:#a6e22e\">subIdx<\/span>: <span style=\"color:#66d9ef\">number<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span> <span style=\"color:#66d9ef\">constructor<\/span>() {\n<\/span><\/span><span style=\"display:flex;\"><span>   <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">subIdx<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">src<\/span>.<span style=\"color:#a6e22e\">addSubscriber<\/span>(<span style=\"color:#a6e22e\">value<\/span> <span style=\"color:#f92672\">=&gt;<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>     <span style=\"color:#a6e22e\">console<\/span>.<span style=\"color:#a6e22e\">log<\/span>(<span style=\"color:#a6e22e\">value<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>   });\n<\/span><\/span><span style=\"display:flex;\"><span> }\n<\/span><\/span><span style=\"display:flex;\"><span> \n<\/span><\/span><span style=\"display:flex;\"><span> <span style=\"color:#a6e22e\">onDestroy() {<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>   <span style=\"color:#75715e\">\/\/ the equivalent of `unsubscribe()`\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>   <span style=\"color:#a6e22e\">src<\/span>.<span style=\"color:#a6e22e\">removeSubscriber<\/span>(<span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">subIdx<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span> }\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><span style=\"display:flex;\"><span> \n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ creating a new component\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span><span style=\"color:#66d9ef\">let<\/span> <span style=\"color:#a6e22e\">foo<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">new<\/span> <span style=\"color:#a6e22e\">Foo<\/span>(); <span style=\"color:#75715e\">\/\/ Foo {subIdx: 0}\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span> \n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ sending data to subscribers\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span><span style=\"color:#a6e22e\">src<\/span>.<span style=\"color:#a6e22e\">next<\/span>(<span style=\"color:#e6db74\">&#34;sending data for the first time&#34;<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ console output: `sending data for the first time`\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span> \n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ destroying the component - without calling `onDestroy`\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span><span style=\"color:#a6e22e\">foo<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">null<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span> \n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">src<\/span>.<span style=\"color:#a6e22e\">next<\/span>(<span style=\"color:#e6db74\">&#34;sending data for the second time&#34;<\/span>); <span style=\"color:#75715e\">\/\/ the subscriber is still there\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ console output: `sending data for the second time`\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span> \n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ registering a new instance - Foo {subIdx: 1}\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ at this point, a new subscriber has been created\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span><span style=\"color:#a6e22e\">foo<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">new<\/span> <span style=\"color:#a6e22e\">Foo<\/span>();\n<\/span><\/span><span style=\"display:flex;\"><span> \n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">src<\/span>.<span style=\"color:#a6e22e\">next<\/span>(<span style=\"color:#e6db74\">&#34;sending data for the third time&#34;<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ console output: `sending data for the third time`\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ console output: `sending data for the third time`\n<\/span><\/span><\/span><\/code><\/pre><\/div><p><em>You can also play around with the code above in this <a href=\"https:\/\/stackblitz.com\/edit\/memory-leaks-simplified-version?file=index.ts\" target=\"_blank\" rel=\"noopener\">StackBlitz<\/a>.<\/em><\/p>\n<p>After <code>src.next('test2')<\/code>, we can see <code>'foo'<\/code> being logged twice, which indicates a memory leak. Something very similar happens with Subjects and their subscribers.<\/p>\n<p>Usually, this sort of problems take place when the source is infinite(it will not <code>complete<\/code>\/<code>error<\/code>, like a global service that is used by components). But there are cases when unsubscribing is not necessary. For instance, when the Subject can no longer be referenced when its container is destroyed or nulled out, which is what happens with <code>ActivatedRoute<\/code> or form control&rsquo;s Subjects(<code>valueChanges<\/code>, <code>statusChanges<\/code>) when the component is destroyed.<\/p>\n<h2 id=\"conclusion\">\n  <span>\n  Conclusion\n  <\/span>\n  <a href=\"#conclusion\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><p>I hope that with this short article, the reason why memory leaks occur when using RxJS&rsquo; Subjects is a bit more clearer. To summarize, it all comes down to the fact that a Subject keeps track of subscribers with the help of a list and when a subscriber shouldn&rsquo;t be there anymore, its <code>unsubscribe()<\/code> method should be called. Otherwise, there will be some unexpected results.<\/p>\n<p>Thanks for reading!<\/p>\n"},{"title":"Angular Router: Revealing some interesting facts and features","link":"https:\/\/andreigatej.dev\/blog\/angular-router-interesting-facts-and-features\/","pubDate":"Wed, 28 Oct 2020 00:00:00 +0000","guid":"https:\/\/andreigatej.dev\/blog\/angular-router-interesting-facts-and-features\/","description":"<p><em>This article has been published on <a href=\"https:\/\/indepth.dev\/posts\/1379\/angular-router-revealing-some-interesting-facts-and-features\" target=\"_blank\" rel=\"noopener\">indepth.dev<\/a>.<\/em><\/p>\n<h2 id=\"introduction\">\n  <span>\n  Introduction\n  <\/span>\n  <a href=\"#introduction\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><p>It is undeniable that the <code>angular\/router<\/code> package is full of useful features. This time, instead of focusing on an a single and precise topic, we&rsquo;re going to look at some interesting facts and properties of this package that you might not be aware of. These can range from sorts of comparisons(e.g <code>relative<\/code> vs <code>absolute<\/code> redirects) to nonobvious details(e.g <code>RouterOutlet<\/code>&rsquo;s hierarchy; how the URL is set in the browser etc).<\/p>\n<p>This article assumes the reader has some basic knowledge of Angular Router(e.g. route navigations, outlets). By the end of it, you should have a better understanding of what this package is capable of.<\/p>\n<h2 id=\"relative-vs-absolute-redirects\">\n  <span>\n  Relative vs Absolute Redirects\n  <\/span>\n  <a href=\"#relative-vs-absolute-redirects\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><p>When setting up the route configuration array, we often come across the <code>redirectTo<\/code> property. Although its purpose is defined by its name, it also has a few interesting traits that are worth examining.<\/p>\n<p>The path this property takes in can either be relative or absolute. Before revealing the differences between these 2 options, let&rsquo;s see what configuration we&rsquo;ll be using:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">routes<\/span>: <span style=\"color:#66d9ef\">Routes<\/span> <span style=\"color:#f92672\">=<\/span> [\n<\/span><\/span><span style=\"display:flex;\"><span>  {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">path<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;&#39;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">pathMatch<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;full&#39;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">component<\/span>: <span style=\"color:#66d9ef\">DefaultComponent<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>  },\n<\/span><\/span><span style=\"display:flex;\"><span>  {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">path<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;a\/b&#39;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">component<\/span>: <span style=\"color:#66d9ef\">AComponent<\/span>, <span style=\"color:#75715e\">\/\/ reachable from `DefaultComponent`\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>    <span style=\"color:#a6e22e\">children<\/span><span style=\"color:#f92672\">:<\/span> [\n<\/span><\/span><span style=\"display:flex;\"><span>      {\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#75715e\">\/\/ Reached when `redirectTo: &#39;err-page&#39;` (relative) is used\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>        <span style=\"color:#a6e22e\">path<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;err-page&#39;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#a6e22e\">component<\/span>: <span style=\"color:#66d9ef\">BComponent<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>      },\n<\/span><\/span><span style=\"display:flex;\"><span>      {\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#a6e22e\">path<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;**&#39;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#a6e22e\">redirectTo<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;err-page&#39;<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>      },\n<\/span><\/span><span style=\"display:flex;\"><span>    ],\n<\/span><\/span><span style=\"display:flex;\"><span>  },\n<\/span><\/span><span style=\"display:flex;\"><span>  {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#75715e\">\/\/ Reached when `redirectTo: &#39;\/err-page&#39;` is used\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>    <span style=\"color:#a6e22e\">path<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;err-page&#39;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">component<\/span>: <span style=\"color:#66d9ef\">DComponent<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  }\n<\/span><\/span><span style=\"display:flex;\"><span>]\n<\/span><\/span><\/code><\/pre><\/div><p><em>A StackBlitz demo can be found <a href=\"https:\/\/stackblitz.com\/edit\/exp-routing-redirect-abs-vs-nonabs-path?file=src%2Fapp%2Fapp.module.ts\" target=\"_blank\" rel=\"noopener\">here<\/a><\/em>.<\/p>\n<p>With the current option, <code>redirectTo: 'err-page'<\/code>(relative path), the <code>BComponent<\/code> will be used. If we&rsquo;d change it to <code>\/err-page<\/code>, then the <code>DComponent<\/code> should be used. As a generalization, we could say that one of the difference between <code>redirectTo: 'foo\/bar'<\/code> and <code>redirectTo: '\/foo\/bar'<\/code> is that when using an absolute path, the search for the next configuration object will start from the <strong>root<\/strong>, that is, the first, outermost array of routes.<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">routes<\/span>: <span style=\"color:#66d9ef\">Routes<\/span> <span style=\"color:#f92672\">=<\/span> [\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#75715e\">\/\/ **STARTS FROM HERE**\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>  {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#75715e\">\/* ... *\/<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>  },\n<\/span><\/span><span style=\"display:flex;\"><span>  {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#75715e\">\/* ... *\/<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">children<\/span><span style=\"color:#f92672\">:<\/span> [\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#75715e\">\/* ... *\/<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>      {\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#a6e22e\">path<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;**&#39;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#a6e22e\">redirectTo<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;\/err-page&#39;<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>      },\n<\/span><\/span><span style=\"display:flex;\"><span>    ],\n<\/span><\/span><span style=\"display:flex;\"><span>  },\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>  {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">path<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;err-page&#39;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#75715e\">\/* ... *\/<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>  }\n<\/span><\/span><span style=\"display:flex;\"><span>]\n<\/span><\/span><\/code><\/pre><\/div><p>Whereas when using a relative path, the search will start from the first route in the array from where the redirect operation has started:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">routes<\/span>: <span style=\"color:#66d9ef\">Routes<\/span> <span style=\"color:#f92672\">=<\/span> [\n<\/span><\/span><span style=\"display:flex;\"><span>  {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#75715e\">\/* ... *\/<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>  },\n<\/span><\/span><span style=\"display:flex;\"><span>  {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#75715e\">\/* ... *\/<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">children<\/span><span style=\"color:#f92672\">:<\/span> [\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#75715e\">\/\/ **STARTS FROM HERE**\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>      <span style=\"color:#75715e\">\/* ... *\/<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>      {\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#a6e22e\">path<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;**&#39;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#a6e22e\">redirectTo<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;err-page&#39;<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>      },\n<\/span><\/span><span style=\"display:flex;\"><span>    ],\n<\/span><\/span><span style=\"display:flex;\"><span>  },\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>  {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">path<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;err-page&#39;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#75715e\">\/* ... *\/<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>  }\n<\/span><\/span><span style=\"display:flex;\"><span>]\n<\/span><\/span><\/code><\/pre><\/div><p>Furthermore, another great feature that absolute redirects have is that they can include named outlets:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span>{\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">path<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;a\/b&#39;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">component<\/span>: <span style=\"color:#66d9ef\">AComponent<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">children<\/span><span style=\"color:#f92672\">:<\/span> [\n<\/span><\/span><span style=\"display:flex;\"><span>    {\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#a6e22e\">path<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;&#39;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#a6e22e\">component<\/span>: <span style=\"color:#66d9ef\">BComponent<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>    },\n<\/span><\/span><span style=\"display:flex;\"><span>    {\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#a6e22e\">path<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;c&#39;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#a6e22e\">outlet<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;c-outlet&#39;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#a6e22e\">component<\/span>: <span style=\"color:#66d9ef\">CComponent<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>    },\n<\/span><\/span><span style=\"display:flex;\"><span>  ],\n<\/span><\/span><span style=\"display:flex;\"><span>},\n<\/span><\/span><span style=\"display:flex;\"><span>{\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">path<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;d-route&#39;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">redirectTo<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;\/a\/b\/(c-outlet:c)&#39;<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p><em><a href=\"https:\/\/stackblitz.com\/edit\/exp-routing-redirect-named-outlet?file=src%2Fapp%2Fapp.module.ts\" target=\"_blank\" rel=\"noopener\">StackBlitz demo<\/a><\/em>.<\/p>\n<p>It is worth mentioning that an absolute redirect operation can occur only once during a route transition.<\/p>\n<p>The <code>path<\/code> property which resides in the same configuration object as the <code>redirectTo<\/code> property poses a few more interesting possibilities. The <code>path<\/code> property can take in a simple string which defines a route path, or <code>'**'<\/code>, making it a wildcard route. This route will match any route it is compared against. Now, let&rsquo;s have a look at the options a non-wildcard route gives us.<\/p>\n<p>Firstly, with a non-wildcard route we can reuse the <code>query params<\/code> and the <code>positional params<\/code>(the params that follow the <code>:nameOfParam<\/code> model) from the current issued URL:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">routes<\/span>: <span style=\"color:#66d9ef\">Routes<\/span> <span style=\"color:#f92672\">=<\/span> [\n<\/span><\/span><span style=\"display:flex;\"><span>  {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">path<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;a\/b&#39;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">component<\/span>: <span style=\"color:#66d9ef\">AComponent<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">children<\/span><span style=\"color:#f92672\">:<\/span> [\n<\/span><\/span><span style=\"display:flex;\"><span>      {\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#75715e\">\/\/ Reached when `redirectTo: &#39;err-page&#39;` (relative) is used\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>        <span style=\"color:#a6e22e\">path<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;err-page&#39;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#a6e22e\">component<\/span>: <span style=\"color:#66d9ef\">BComponent<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>      },\n<\/span><\/span><span style=\"display:flex;\"><span>      {\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#a6e22e\">path<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;c\/:id&#39;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#75715e\">\/\/ foo=:foo - get the value of the `foo` query param that \n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>        <span style=\"color:#75715e\">\/\/ exists in the URL that against this route\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>        <span style=\"color:#75715e\">\/\/ it works for relative paths as well: `err-page\/:id?errored=true&amp;foo=:foo`\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>        <span style=\"color:#a6e22e\">redirectTo<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;\/err-page\/:id?errored=true&amp;foo=:foo&#39;<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>      },\n<\/span><\/span><span style=\"display:flex;\"><span>    ],\n<\/span><\/span><span style=\"display:flex;\"><span>  },\n<\/span><\/span><span style=\"display:flex;\"><span>  {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#75715e\">\/\/ Reached when `redirectTo: &#39;\/err-page&#39;` is used\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>    <span style=\"color:#a6e22e\">path<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;err-page\/:id&#39;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">component<\/span>: <span style=\"color:#66d9ef\">DComponent<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  }\n<\/span><\/span><span style=\"display:flex;\"><span>]\n<\/span><\/span><\/code><\/pre><\/div><p><em><a href=\"https:\/\/stackblitz.com\/edit\/exp-routing-redirect-non-wildcard?file=src%2Fapp%2Fapp.module.ts\" target=\"_blank\" rel=\"noopener\">StackBlitz demo<\/a>.<\/em><\/p>\n<p>In the above snippet, we can see that this pattern is followed<\/p>\n<ul>\n<li><code>?name=:foo<\/code> - the <code>foo<\/code> query param is taken from the actual url<\/li>\n<li><code>path: 'a\/:id'<\/code>, <code>redirectTo: 'err-page\/:id'<\/code> - the <code>id<\/code> positional param is taken from <code>a\/:id<\/code><\/li>\n<\/ul>\n<p>And here is how we&rsquo;d navigate to such route:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-html\" data-lang=\"html\"><span style=\"display:flex;\"><span>&lt;<span style=\"color:#f92672\">button<\/span> <span style=\"color:#a6e22e\">routerLink<\/span><span style=\"color:#f92672\">=<\/span><span style=\"color:#e6db74\">&#34;a\/b\/c\/123&#34;<\/span> <span style=\"color:#960050;background-color:#1e0010\">[<\/span><span style=\"color:#a6e22e\">queryParams<\/span><span style=\"color:#960050;background-color:#1e0010\">]=&#34;{<\/span> <span style=\"color:#a6e22e\">foo:<\/span> <span style=\"color:#960050;background-color:#1e0010\">&#39;<\/span><span style=\"color:#a6e22e\">foovalue<\/span><span style=\"color:#960050;background-color:#1e0010\">&#39;<\/span> <span style=\"color:#960050;background-color:#1e0010\">}&#34;<\/span>&gt;...&lt;\/<span style=\"color:#f92672\">button<\/span>&gt;\n<\/span><\/span><\/code><\/pre><\/div><p>Also, when using a <code>non-wildcard<\/code> path and a <code>relative<\/code> redirect, that extra segments of the URL will be added to the <code>redirectTo<\/code>&rsquo;s segments<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">routes<\/span>: <span style=\"color:#66d9ef\">Routes<\/span> <span style=\"color:#f92672\">=<\/span> [\n<\/span><\/span><span style=\"display:flex;\"><span>  {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">path<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;a\/b&#39;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">component<\/span>: <span style=\"color:#66d9ef\">AComponent<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">children<\/span><span style=\"color:#f92672\">:<\/span> [\n<\/span><\/span><span style=\"display:flex;\"><span>      {\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#a6e22e\">path<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;err-page\/test&#39;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#a6e22e\">component<\/span>: <span style=\"color:#66d9ef\">BComponent<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>      },\n<\/span><\/span><span style=\"display:flex;\"><span>      {\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#75715e\">\/\/ `redirectTo: &#39;\/err-page&#39;` - would lead to errors\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>        <span style=\"color:#a6e22e\">path<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;c&#39;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#a6e22e\">redirectTo<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;err-page&#39;<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>      },\n<\/span><\/span><span style=\"display:flex;\"><span>    ],\n<\/span><\/span><span style=\"display:flex;\"><span>  },\n<\/span><\/span><span style=\"display:flex;\"><span>  \n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#75715e\">\/\/ this could never be reached from `path: &#39;c&#39;`\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>  {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">path<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;err-page\/test&#39;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">component<\/span>: <span style=\"color:#66d9ef\">DComponent<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  }\n<\/span><\/span><span style=\"display:flex;\"><span>]\n<\/span><\/span><\/code><\/pre><\/div><blockquote>\n<p>This only works for <code>relative<\/code> redirects.<\/p>\n<\/blockquote>\n<p>So, we can reach <code>BComponent<\/code>&rsquo;s route this way:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-html\" data-lang=\"html\"><span style=\"display:flex;\"><span>&lt;<span style=\"color:#f92672\">button<\/span> <span style=\"color:#a6e22e\">routerLink<\/span><span style=\"color:#f92672\">=<\/span><span style=\"color:#e6db74\">&#34;a\/b\/c\/test&#34;<\/span>&gt;...&lt;\/<span style=\"color:#f92672\">button<\/span>&gt;\n<\/span><\/span><\/code><\/pre><\/div><p><em><a href=\"https:\/\/stackblitz.com\/edit\/exp-routing-redirect-non-wildcard-relative?file=src%2Fapp%2Fapp.module.ts\" target=\"_blank\" rel=\"noopener\">StackBlitz demo<\/a>.<\/em><\/p>\n<p>Things can even get a bit more complicated(and interesting), when we consider <code>matrix params<\/code>(e.g <code>;k1=v1;k2=v2<\/code>) as well. As a side note, <code>positional params<\/code> are those which we explicitly define in the route paths(e.g <code>\/:id<\/code>), whereas <code>matrix params<\/code> are taken together with their path. Internally, Angular uses entities such as <code>UrlSegmentGroup<\/code>, <code>UrlSegment<\/code> to achieve its features. If we peek at the <a href=\"https:\/\/github.com\/angular\/angular\/blob\/master\/packages\/router\/src\/url_tree.ts#L209-L212\" target=\"_blank\" rel=\"noopener\"><code>UrlSegment<\/code>&rsquo;s implementation<\/a>, we can see mentioned matrix params. With this in mind, let&rsquo;s see an example:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">routes<\/span>: <span style=\"color:#66d9ef\">Routes<\/span> <span style=\"color:#f92672\">=<\/span> [\n<\/span><\/span><span style=\"display:flex;\"><span>  {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">path<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;d\/a\/:id\/e&#39;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">component<\/span>: <span style=\"color:#66d9ef\">DComponent<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  },\n<\/span><\/span><span style=\"display:flex;\"><span>  {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#75715e\">\/\/ `redirectTo: &#39;\/d\/a\/:id\/e&#39;` would work as well\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>    <span style=\"color:#a6e22e\">path<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;a\/:id&#39;<\/span>, \n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">redirectTo<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;d\/a\/:id\/e&#39;<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>  },\n<\/span><\/span><span style=\"display:flex;\"><span>]\n<\/span><\/span><\/code><\/pre><\/div><p>If we start a navigation with<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-html\" data-lang=\"html\"><span style=\"display:flex;\"><span>&lt;<span style=\"color:#f92672\">button<\/span> <span style=\"color:#960050;background-color:#1e0010\">[<\/span><span style=\"color:#a6e22e\">routerLink<\/span><span style=\"color:#960050;background-color:#1e0010\">]=&#34;[&#39;\/<\/span><span style=\"color:#a6e22e\">a<\/span><span style=\"color:#960050;background-color:#1e0010\">&#39;,<\/span> <span style=\"color:#960050;background-color:#1e0010\">{<\/span> <span style=\"color:#a6e22e\">p1:<\/span> <span style=\"color:#a6e22e\">1<\/span> <span style=\"color:#960050;background-color:#1e0010\">},<\/span> <span style=\"color:#960050;background-color:#1e0010\">&#39;<\/span><span style=\"color:#a6e22e\">1<\/span><span style=\"color:#960050;background-color:#1e0010\">&#39;,<\/span> <span style=\"color:#960050;background-color:#1e0010\">{<\/span> <span style=\"color:#a6e22e\">p2:<\/span> <span style=\"color:#a6e22e\">2<\/span><span style=\"color:#960050;background-color:#1e0010\">,<\/span> <span style=\"color:#a6e22e\">p3:<\/span> <span style=\"color:#a6e22e\">3<\/span> <span style=\"color:#960050;background-color:#1e0010\">}]&#34;<\/span>&gt;...&lt;\/<span style=\"color:#f92672\">button<\/span>&gt;\n<\/span><\/span><\/code><\/pre><\/div><p><em><a href=\"https:\/\/stackblitz.com\/edit\/exp-routing-redirect-non-wildcard-relative-matrix-params?file=src%2Fapp%2Fapp.module.ts\" target=\"_blank\" rel=\"noopener\">StackBlitz demo.<\/a><\/em><\/p>\n<p>the <code>DComponent<\/code>&rsquo;s route will be activated and will end up having this URL: <code>...\/d\/a;p1=1\/1;p2=2;p3=3\/e<\/code><\/p>\n<p>First of all, <code>['a\/path', { p1, p2, p3 }]<\/code> is the way to pass matrix params to a segment. The matrix params will be bound to the precedent path. Then, as we&rsquo;ve learnt from the previous paragraphs, we can use positional params that are present in the current route in the <code>redirectTo<\/code> path. The important thing to notice is that the matrix params of a given segment will be preserved in the new navigation&rsquo;s path, if used in <code>redirectTo<\/code>.<\/p>\n<p>Lastly, it is should be mentioned that wildcard routes can only reuse <code>query params<\/code>. Positional params are not possible because in order to reuse such params, they first have to find their match in the <code>path<\/code> property and since <code>'**'<\/code> is used, they can&rsquo;t be used any further in <code>redirectTo<\/code>.<\/p>\n<p>Here&rsquo;s is a <a href=\"https:\/\/stackblitz.com\/edit\/exp-routing-redirect-wilcard-queryparams?file=src\/app\/app.module.ts\" target=\"_blank\" rel=\"noopener\">StackBlitz demo<\/a> that illustrates how to reuse query params in a wildcard route.<\/p>\n<h2 id=\"routernavigate-vs-routernavigatebyurl\">\n  <span>\n  <code>Router.navigate<\/code> vs <code>Router.navigateByUrl<\/code>\n  <\/span>\n  <a href=\"#routernavigate-vs-routernavigatebyurl\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><p>Although they both have the same purpose, to start a new navigation, they also have a few dissimilarities. Before revealing them, it&rsquo;s important to know that Angular Router operates on a <code>UrlTree<\/code> in order perform the navigation. A <code>UrlTree<\/code> can be thought of a deserialized version of a URL(a string).<\/p>\n<p><code>navigate()<\/code> will create the <code>UrlTree<\/code> needed for the navigation based on the current <code>UrlTree<\/code>. This might be a bit tricky to use, since in some cases it is needed to provide the <code>relativeTo<\/code> route as well: <code>navigate(commandsArray, { relativeTo: ActivatedRouteInstance })<\/code>. If the <code>relativeTo<\/code> option is not specified, the root <code>ActivatedRoute<\/code> will be chosen.<\/p>\n<p>The <code>navigateByUrl()<\/code> method will create a new <code>UrlTree<\/code>, regardless of the current one.<\/p>\n<p>If you&rsquo;d like to play around with some examples, you can find them in this <a href=\"https:\/\/stackblitz.com\/edit\/exp-routing-replace?file=src%2Fapp%2Fcomponents%2Fb.component.ts\" target=\"_blank\" rel=\"noopener\">StackBlitz demo<\/a><\/p>\n<h2 id=\"how-is-the-url-set-in-the-browser-\">\n  <span>\n  How is the URL set in the browser ?\n  <\/span>\n  <a href=\"#how-is-the-url-set-in-the-browser-\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><p>Under the hood, Angular Router simply uses the native <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/API\/History\" target=\"_blank\" rel=\"noopener\">history API<\/a>. For example, when navigating to a new route, <code>\/user\/:id<\/code>, the <code>history.pushState<\/code> method is invoked. Similarly, it uses <code>history.replaceState<\/code> when navigating to the same path or when the <code>replaceUrl<\/code> option is set to <code>true<\/code>.<\/p>\n<p>Here&rsquo;s a <a href=\"https:\/\/stackblitz.com\/edit\/exp-routing-replace-state?file=src%2Fapp%2Fapp.module.ts\" target=\"_blank\" rel=\"noopener\">StackBlitz demo<\/a> that demonstrates the behavior that can be achieved with the <code>replaceUrl<\/code> option.<\/p>\n<h2 id=\"the-skiplocationchange-option\">\n  <span>\n  The <code>skipLocationChange<\/code> option\n  <\/span>\n  <a href=\"#the-skiplocationchange-option\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><p>What this options does is to ensure that the <code>Router<\/code>&rsquo;s method which is responsible for setting the browser&rsquo;s URL, thus adding items to the history&rsquo;s stack, will not be called. However, the <code>Router<\/code>&rsquo;s internal status will be updated accordingly(e.g route params, query params, anything that can be <code>observed<\/code> from <code>ActivatedRoute<\/code>).<\/p>\n<p>Here you can find a <a href=\"https:\/\/stackblitz.com\/edit\/exp-routing-skiplocationchange?file=src%2Fapp%2Fcomponents%2Fa.component.ts\" target=\"_blank\" rel=\"noopener\">StackBlitz demo<\/a>.<\/p>\n<p>As you can see, because this option is used, the <code>\/d<\/code> will not even be shown in the address bar. Despite this, the <code>\/d<\/code> route&rsquo;s component (<code>DComponent<\/code>) will be loaded.<\/p>\n<h2 id=\"the-hierarchy-created-by-the-routeroutlet-directive\">\n  <span>\n  The hierarchy created by the <code>RouterOutlet<\/code> directive\n  <\/span>\n  <a href=\"#the-hierarchy-created-by-the-routeroutlet-directive\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><p>An Angular Router&rsquo;s fundamental unit is the <code>RouterOutlet<\/code> directive(identifiable as <code>router-outlet<\/code>). Without it, it would not be possible to actually show something in the browser. But, as we&rsquo;ve seen while building Angular applications, it&rsquo;s not rare the case when we end up having nested <code>router-outlet<\/code>blog_tags. Speaking of that, let&rsquo;s assume we have a route configuration like this:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ in order to be able to see the `BarComponent`&#39;s view, we&#39;d need to have 2 `router-outlet`\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ 1 in `app.component.html` -&gt; needed to render `FooComponent`\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ 1 in `foo.component` -&gt; needed to render `BarComponent`\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">routes<\/span> <span style=\"color:#f92672\">=<\/span> [\n<\/span><\/span><span style=\"display:flex;\"><span>  {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">path<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;foo&#39;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">component<\/span>: <span style=\"color:#66d9ef\">FooComponent<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">children<\/span><span style=\"color:#f92672\">:<\/span> [\n<\/span><\/span><span style=\"display:flex;\"><span>      { <span style=\"color:#a6e22e\">path<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;bar\/:id&#39;<\/span>, <span style=\"color:#a6e22e\">component<\/span>: <span style=\"color:#66d9ef\">BarComponent<\/span> }   \n<\/span><\/span><span style=\"display:flex;\"><span>    ]\n<\/span><\/span><span style=\"display:flex;\"><span>  }\n<\/span><\/span><span style=\"display:flex;\"><span>];\n<\/span><\/span><\/code><\/pre><\/div><p>and let&rsquo;s also assume that we inject <code>ActivatedRoute<\/code> inside <code>BarComponent<\/code>. Have you ever wondered why, when navigating to <code>foo\/bar\/123<\/code>, the <code>ActivatedRoute<\/code> instance is the <em>correct<\/em> one(e.g it exposes the <code>params<\/code>, <code>queryParams<\/code> that are related to <code>bar\/:id<\/code> route)? It&rsquo;s again an important detail that&rsquo;s handled by the <code>RouterOutlet<\/code> directive. In this section, we&rsquo;re going to explore how is this achieved(<strong>hint<\/strong>: it involves creating a custom injector!).<\/p>\n<p>Let&rsquo;s consider a simpler scenario - we have a route configuration like this:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ app.module.ts\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span><span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">routes<\/span> <span style=\"color:#f92672\">=<\/span> [\n<\/span><\/span><span style=\"display:flex;\"><span>  {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">path<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;foo&#39;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">component<\/span>: <span style=\"color:#66d9ef\">FooComponent<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  }\n<\/span><\/span><span style=\"display:flex;\"><span>]\n<\/span><\/span><\/code><\/pre><\/div><p>And now, in order to be able to see the rendered view on <code>\/foo<\/code>, we need to insert the <code>router-outlet<\/code> <em>tag<\/em> in <code>app.component.html<\/code><\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-html\" data-lang=\"html\"><span style=\"display:flex;\"><span>&lt;<span style=\"color:#f92672\">button<\/span> <span style=\"color:#a6e22e\">routerLink<\/span><span style=\"color:#f92672\">=<\/span><span style=\"color:#e6db74\">&#34;\/foo&#34;<\/span>&gt;Go to \/foo route&lt;\/<span style=\"color:#f92672\">button<\/span>&gt;\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>&lt;<span style=\"color:#f92672\">router-outlet<\/span>&gt;&lt;\/<span style=\"color:#f92672\">router-outlet<\/span>&gt;\n<\/span><\/span><\/code><\/pre><\/div><p>This is where things start to get interesting. Let&rsquo;s see what the <a href=\"https:\/\/github.com\/angular\/angular\/blob\/master\/packages\/router\/src\/directives\/router_outlet.ts#L71-L77\" target=\"_blank\" rel=\"noopener\">first steps of initialization<\/a> are:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">constructor<\/span>(\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">private<\/span> <span style=\"color:#a6e22e\">parentContexts<\/span>: <span style=\"color:#66d9ef\">ChildrenOutletContexts<\/span>, <span style=\"color:#66d9ef\">private<\/span> <span style=\"color:#a6e22e\">location<\/span>: <span style=\"color:#66d9ef\">ViewContainerRef<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">private<\/span> <span style=\"color:#a6e22e\">resolver<\/span>: <span style=\"color:#66d9ef\">ComponentFactoryResolver<\/span>, <span style=\"color:#66d9ef\">@Attribute<\/span>(<span style=\"color:#e6db74\">&#39;name&#39;<\/span>) <span style=\"color:#a6e22e\">name<\/span>: <span style=\"color:#66d9ef\">string<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">private<\/span> <span style=\"color:#a6e22e\">changeDetector<\/span>: <span style=\"color:#66d9ef\">ChangeDetectorRef<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#75715e\">\/\/ in case we&#39;re using named outlet, we provide the `name` property\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>  <span style=\"color:#75715e\">\/\/ as we can see, it defaults to `PRIMARY_OUTLET`(`primary`)\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>  <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">name<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">name<\/span> <span style=\"color:#f92672\">||<\/span> <span style=\"color:#a6e22e\">PRIMARY_OUTLET<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">parentContexts<\/span>.<span style=\"color:#a6e22e\">onChildOutletCreated<\/span>(<span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">name<\/span>, <span style=\"color:#66d9ef\">this<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p>We can already see something which is not that common: <code>ChildrenOutletContexts<\/code>. Let&rsquo;s see <a href=\"https:\/\/github.com\/angular\/angular\/blob\/master\/packages\/router\/src\/router_outlet_context.ts#L33\" target=\"_blank\" rel=\"noopener\">what it is about<\/a>:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">export<\/span> <span style=\"color:#66d9ef\">class<\/span> <span style=\"color:#a6e22e\">ChildrenOutletContexts<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#75715e\">\/\/ contexts for child outlets, by name.\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>  <span style=\"color:#66d9ef\">private<\/span> <span style=\"color:#a6e22e\">contexts<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">new<\/span> <span style=\"color:#a6e22e\">Map<\/span>&lt;<span style=\"color:#f92672\">string<\/span><span style=\"color:#960050;background-color:#1e0010\">,<\/span> <span style=\"color:#a6e22e\">OutletContext<\/span>&gt;();\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#75715e\">\/** Called when a `RouterOutlet` directive is instantiated *\/<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">onChildOutletCreated<\/span>(<span style=\"color:#a6e22e\">childName<\/span>: <span style=\"color:#66d9ef\">string<\/span>, <span style=\"color:#a6e22e\">outlet<\/span>: <span style=\"color:#66d9ef\">RouterOutlet<\/span>)<span style=\"color:#f92672\">:<\/span> <span style=\"color:#66d9ef\">void<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">context<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">getOrCreateContext<\/span>(<span style=\"color:#a6e22e\">childName<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">context<\/span>.<span style=\"color:#a6e22e\">outlet<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">outlet<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">contexts<\/span>.<span style=\"color:#66d9ef\">set<\/span>(<span style=\"color:#a6e22e\">childName<\/span>, <span style=\"color:#a6e22e\">context<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>  }\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#75715e\">\/* ... *\/<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">getOrCreateContext<\/span>(<span style=\"color:#a6e22e\">childName<\/span>: <span style=\"color:#66d9ef\">string<\/span>)<span style=\"color:#f92672\">:<\/span> <span style=\"color:#a6e22e\">OutletContext<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">let<\/span> <span style=\"color:#a6e22e\">context<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">getContext<\/span>(<span style=\"color:#a6e22e\">childName<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#f92672\">!<\/span><span style=\"color:#a6e22e\">context<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#a6e22e\">context<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">new<\/span> <span style=\"color:#a6e22e\">OutletContext<\/span>();\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">contexts<\/span>.<span style=\"color:#66d9ef\">set<\/span>(<span style=\"color:#a6e22e\">childName<\/span>, <span style=\"color:#a6e22e\">context<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>    }\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#a6e22e\">context<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>  }\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">getContext<\/span>(<span style=\"color:#a6e22e\">childName<\/span>: <span style=\"color:#66d9ef\">string<\/span>)<span style=\"color:#f92672\">:<\/span> <span style=\"color:#a6e22e\">OutletContext<\/span><span style=\"color:#f92672\">|<\/span><span style=\"color:#66d9ef\">null<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">contexts<\/span>.<span style=\"color:#66d9ef\">get<\/span>(<span style=\"color:#a6e22e\">childName<\/span>) <span style=\"color:#f92672\">||<\/span> <span style=\"color:#66d9ef\">null<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>  }\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">export<\/span> <span style=\"color:#66d9ef\">class<\/span> <span style=\"color:#a6e22e\">OutletContext<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">outlet<\/span>: <span style=\"color:#66d9ef\">RouterOutlet<\/span><span style=\"color:#f92672\">|<\/span><span style=\"color:#66d9ef\">null<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">null<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">route<\/span>: <span style=\"color:#66d9ef\">ActivatedRoute<\/span><span style=\"color:#f92672\">|<\/span><span style=\"color:#66d9ef\">null<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">null<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">resolver<\/span>: <span style=\"color:#66d9ef\">ComponentFactoryResolver<\/span><span style=\"color:#f92672\">|<\/span><span style=\"color:#66d9ef\">null<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">null<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">children<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">new<\/span> <span style=\"color:#a6e22e\">ChildrenOutletContexts<\/span>();\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">attachRef<\/span>: <span style=\"color:#66d9ef\">ComponentRef<\/span>&lt;<span style=\"color:#f92672\">any<\/span>&gt;<span style=\"color:#f92672\">|<\/span><span style=\"color:#66d9ef\">null<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">null<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p>So, when any <code>RouterDirective<\/code> is created, it will right away invoke <code>ChildrenOutletContexts.onChildOutletCreated()<\/code>. Then, it will either reuse an existing <em>context<\/em> or it create a new one, which is the current situation. We&rsquo;ve introduced the <em>context<\/em> concept and it can be accurately described by the <code>OutletContext<\/code>. An interesting thing to notice here is that a <em>context<\/em> has a <code>children<\/code> property, which points <code>ChildrenOutletContexts<\/code>. What this means is that we can visualize this process as a tree of <em>contexts<\/em>, more exactly a tree of <code>OutletContext<\/code> instances.<\/p>\n<p>What you might wonder now is why the <code>ChildrenOutletContexts<\/code> class needs to maintains a map of <code>OutletContext<\/code>s:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">private<\/span> <span style=\"color:#a6e22e\">contexts<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">new<\/span> <span style=\"color:#a6e22e\">Map<\/span>&lt;<span style=\"color:#f92672\">string<\/span><span style=\"color:#960050;background-color:#1e0010\">,<\/span> <span style=\"color:#a6e22e\">OutletContext<\/span>&gt;();\n<\/span><\/span><\/code><\/pre><\/div><p>Even if this question didn&rsquo;t not immediately come to mind, it&rsquo;s a question that&rsquo;s worth asking. To answer this, let&rsquo;s recall that we can also have <strong>named outlets<\/strong>. So, what would the <code>context<\/code> <code>Map<\/code> instance look like if we would add these? :<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">routes<\/span> <span style=\"color:#f92672\">=<\/span> [\n<\/span><\/span><span style=\"display:flex;\"><span>  {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">path<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;foo&#39;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">component<\/span>: <span style=\"color:#66d9ef\">FooComponent<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  },\n<\/span><\/span><span style=\"display:flex;\"><span>  {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">path<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;bar&#39;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">component<\/span>: <span style=\"color:#66d9ef\">BarComponent<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">outlet<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;named-bar&#39;<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>  }\n<\/span><\/span><span style=\"display:flex;\"><span>]\n<\/span><\/span><\/code><\/pre><\/div><div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-html\" data-lang=\"html\"><span style=\"display:flex;\"><span><span style=\"color:#75715e\">&lt;!-- app.component.html --&gt;<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>&lt;<span style=\"color:#f92672\">button<\/span> <span style=\"color:#a6e22e\">routerLink<\/span><span style=\"color:#f92672\">=<\/span><span style=\"color:#e6db74\">&#34;\/foo&#34;<\/span>&gt;Go to \/foo route&lt;\/<span style=\"color:#f92672\">button<\/span>&gt;\n<\/span><\/span><span style=\"display:flex;\"><span>&lt;<span style=\"color:#f92672\">button<\/span> <span style=\"color:#960050;background-color:#1e0010\">[<\/span><span style=\"color:#a6e22e\">routerLink<\/span><span style=\"color:#960050;background-color:#1e0010\">]=&#34;[{<\/span> <span style=\"color:#a6e22e\">outlets:<\/span> <span style=\"color:#960050;background-color:#1e0010\">{<\/span> <span style=\"color:#a6e22e\">named-bar:<\/span> <span style=\"color:#a6e22e\">bar<\/span> <span style=\"color:#960050;background-color:#1e0010\">}<\/span> <span style=\"color:#960050;background-color:#1e0010\">}]&#34;<\/span>&gt;Go to \/bar route - named outlet&lt;\/<span style=\"color:#f92672\">button<\/span>&gt;\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>&lt;<span style=\"color:#f92672\">router-outlet<\/span>&gt;&lt;\/<span style=\"color:#f92672\">router-outlet<\/span>&gt;\n<\/span><\/span><span style=\"display:flex;\"><span>&lt;<span style=\"color:#f92672\">router-outlet<\/span> <span style=\"color:#a6e22e\">name<\/span><span style=\"color:#f92672\">=<\/span><span style=\"color:#e6db74\">&#34;named-bar&#34;<\/span>&gt;&lt;\/<span style=\"color:#f92672\">router-outlet<\/span>&gt;\n<\/span><\/span><\/code><\/pre><\/div><p>This time, the <em>main<\/em> <code>ChildrenOutletContexts<\/code> class will have its <code>onChildOutletCreated<\/code> called twice, each time a new <code>OutletContext<\/code> will be created. So, the <code>context<\/code> will be as follows:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span>{\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">primary<\/span>: <span style=\"color:#66d9ef\">OutletContext<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#e6db74\">&#39;named-bar&#39;<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#a6e22e\">OutletContext<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p>If we were to use the <code>tree<\/code>&rsquo;s parlance, we&rsquo;d say that the <code>context<\/code> map&rsquo;s entries represents a <strong>level<\/strong> of a tree and each of its values would go one level deeper.<\/p>\n<p>Let&rsquo;s sharpen this newly learned concept with a help of a <a href=\"https:\/\/stackblitz.com\/edit\/exp-routing-router-outlet?file=src%2Fapp%2Fapp.module.ts\" target=\"_blank\" rel=\"noopener\">StackBlitz demo<\/a>, with the help of which we&rsquo;ll be able to see that this hierarchy is about:<\/p>\n<p>You can visualize it by checking the console&rsquo;s output after clicking the initial button. This might also serve as a debugging technique in case something seems to not go right with your routes.<\/p>\n<p>Now that are more familiar with the <code>RouterOutlet<\/code>&rsquo;s hierarchy, we can now find out what makes possible the <code>ActivatedRoute<\/code> to be scoped to a certain route.<\/p>\n<p><a href=\"https:\/\/github.com\/angular\/angular\/blob\/master\/packages\/router\/src\/directives\/router_outlet.ts#L173\" target=\"_blank\" rel=\"noopener\">At the end<\/a> of the file where <code>RouterOutlet<\/code> is implemented, there is something that&rsquo;s worth some attention:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">class<\/span> <span style=\"color:#a6e22e\">OutletInjector<\/span> <span style=\"color:#66d9ef\">implements<\/span> <span style=\"color:#a6e22e\">Injector<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">constructor<\/span>(\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#66d9ef\">private<\/span> <span style=\"color:#a6e22e\">route<\/span>: <span style=\"color:#66d9ef\">ActivatedRoute<\/span>, <span style=\"color:#66d9ef\">private<\/span> <span style=\"color:#a6e22e\">childContexts<\/span>: <span style=\"color:#66d9ef\">ChildrenOutletContexts<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#66d9ef\">private<\/span> <span style=\"color:#a6e22e\">parent<\/span>: <span style=\"color:#66d9ef\">Injector<\/span>) {}\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">get<\/span>(<span style=\"color:#a6e22e\">token<\/span>: <span style=\"color:#66d9ef\">any<\/span>, <span style=\"color:#a6e22e\">notFoundValue?<\/span>: <span style=\"color:#66d9ef\">any<\/span>)<span style=\"color:#f92672\">:<\/span> <span style=\"color:#66d9ef\">any<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#a6e22e\">token<\/span> <span style=\"color:#f92672\">===<\/span> <span style=\"color:#a6e22e\">ActivatedRoute<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">route<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>    }\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#a6e22e\">token<\/span> <span style=\"color:#f92672\">===<\/span> <span style=\"color:#a6e22e\">ChildrenOutletContexts<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">childContexts<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>    }\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">parent<\/span>.<span style=\"color:#66d9ef\">get<\/span>(<span style=\"color:#a6e22e\">token<\/span>, <span style=\"color:#a6e22e\">notFoundValue<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>  }\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p>If we take a look at how <code>RouterOutlet<\/code> renders something to the screen, we&rsquo;d see how <code>OutletInjector<\/code> is used:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">injector<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">new<\/span> <span style=\"color:#a6e22e\">OutletInjector<\/span>(<span style=\"color:#a6e22e\">activatedRoute<\/span>, <span style=\"color:#a6e22e\">childContexts<\/span>, <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">location<\/span>.<span style=\"color:#a6e22e\">injector<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ this.location - `ViewContainerRef`\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span><span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">activated<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">location<\/span>.<span style=\"color:#a6e22e\">createComponent<\/span>(<span style=\"color:#a6e22e\">factory<\/span>, <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">location<\/span>.<span style=\"color:#a6e22e\">length<\/span>, <span style=\"color:#a6e22e\">injector<\/span>);\n<\/span><\/span><\/code><\/pre><\/div><p>This is what allows us to always get the proper <code>ActivatedRoute<\/code>, when required. When a component injects <code>ActivatedRoute<\/code>, it will look up the injector tree until it finds the first occurrence of the token. The <em>scope<\/em> is actually created when <code>RouterOutlet<\/code> creates a new view. As we can see in <code>OutletInjector<\/code>&rsquo;s implementation, when the <code>ActivatedRoute<\/code> token is required, it will provide the <em>activatedRoute<\/em> that was received when the injector was created.<\/p>\n<h2 id=\"is-it-necessary-to-unsubscribe-from-activatedroutes-properties-\">\n  <span>\n  Is it necessary to unsubscribe from <code>ActivatedRoute<\/code>&rsquo;s properties ?\n  <\/span>\n  <a href=\"#is-it-necessary-to-unsubscribe-from-activatedroutes-properties-\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><p>The short answer is <strong>no<\/strong>.<\/p>\n<p><a href=\"https:\/\/github.com\/angular\/angular\/blob\/master\/packages\/router\/src\/create_router_state.ts#L76-L80\" target=\"_blank\" rel=\"noopener\">Here&rsquo;s<\/a> how an <code>ActivatedRoute<\/code> is created:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">function<\/span> <span style=\"color:#a6e22e\">createActivatedRoute<\/span>(<span style=\"color:#a6e22e\">c<\/span>: <span style=\"color:#66d9ef\">ActivatedRouteSnapshot<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#66d9ef\">new<\/span> <span style=\"color:#a6e22e\">ActivatedRoute<\/span>(\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#66d9ef\">new<\/span> <span style=\"color:#a6e22e\">BehaviorSubject<\/span>(<span style=\"color:#a6e22e\">c<\/span>.<span style=\"color:#a6e22e\">url<\/span>), <span style=\"color:#66d9ef\">new<\/span> <span style=\"color:#a6e22e\">BehaviorSubject<\/span>(<span style=\"color:#a6e22e\">c<\/span>.<span style=\"color:#a6e22e\">params<\/span>), <span style=\"color:#66d9ef\">new<\/span> <span style=\"color:#a6e22e\">BehaviorSubject<\/span>(<span style=\"color:#a6e22e\">c<\/span>.<span style=\"color:#a6e22e\">queryParams<\/span>),\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#66d9ef\">new<\/span> <span style=\"color:#a6e22e\">BehaviorSubject<\/span>(<span style=\"color:#a6e22e\">c<\/span>.<span style=\"color:#a6e22e\">fragment<\/span>), <span style=\"color:#66d9ef\">new<\/span> <span style=\"color:#a6e22e\">BehaviorSubject<\/span>(<span style=\"color:#a6e22e\">c<\/span>.<span style=\"color:#a6e22e\">data<\/span>), <span style=\"color:#a6e22e\">c<\/span>.<span style=\"color:#a6e22e\">outlet<\/span>, <span style=\"color:#a6e22e\">c<\/span>.<span style=\"color:#a6e22e\">component<\/span>, <span style=\"color:#a6e22e\">c<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p>Assuming you have a configuration that looks like this:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span>{\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">path<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;a\/:id&#39;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">component<\/span>: <span style=\"color:#66d9ef\">AComponent<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">children<\/span><span style=\"color:#f92672\">:<\/span> [\n<\/span><\/span><span style=\"display:flex;\"><span>    {\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#a6e22e\">path<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;b&#39;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#a6e22e\">component<\/span>: <span style=\"color:#66d9ef\">BComponent<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>    },\n<\/span><\/span><span style=\"display:flex;\"><span>    {\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#a6e22e\">path<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;c&#39;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#a6e22e\">component<\/span>: <span style=\"color:#66d9ef\">CComponent<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>    },\n<\/span><\/span><span style=\"display:flex;\"><span>  ]\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p>and an issued URL like <code>a\/123\/b<\/code><\/p>\n<p>you&rsquo;d end up having a <strong>tree<\/strong> of <code>ActivatedRoute<\/code>s:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-markdown\" data-lang=\"markdown\"><span style=\"display:flex;\"><span> APP\n<\/span><\/span><span style=\"display:flex;\"><span>  |\n<\/span><\/span><span style=\"display:flex;\"><span>  A\n<\/span><\/span><span style=\"display:flex;\"><span>  |\n<\/span><\/span><span style=\"display:flex;\"><span>  B\n<\/span><\/span><\/code><\/pre><\/div><p>Whenever you schedule a navigation(e.g <code>router.navigateToUrl()<\/code>), the router has to go through some important phases:<\/p>\n<ul>\n<li><strong>apply redirects<\/strong>: checking for redirects, loading lazy-loaded modules, finding <code>NoMatch<\/code> errors<\/li>\n<li><strong>recognize<\/strong>: creating the <code>ActivatedRouteSnapshot<\/code> tree<\/li>\n<li><strong>preactivation<\/strong>: comparing the resulted tree with the current one; this phase also <em>collects<\/em> <code>canActivate<\/code> and <code>canDeactivate<\/code> guards, based on the differences found<\/li>\n<li><strong>running guards<\/strong><\/li>\n<li><strong>create router state<\/strong>: where <code>ActivatedRoute<\/code> tree is created<\/li>\n<li><strong>activating the routes<\/strong>: this is the cherry on the cake and the place where the <code>ActivatedRoute<\/code> tree is leveraged<\/li>\n<\/ul>\n<p>It is also important to mention the role that <code>router-outlet<\/code> plays.<\/p>\n<p>As it has been described in the previous section, Angular keeps track of the <code>router-outlet<\/code>s with the help of a <code>Map<\/code> object.<\/p>\n<p>So, for our route configuration:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span>{\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">path<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;a\/:id&#39;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">component<\/span>: <span style=\"color:#66d9ef\">AComponent<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">children<\/span><span style=\"color:#f92672\">:<\/span> [\n<\/span><\/span><span style=\"display:flex;\"><span>    {\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#a6e22e\">path<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;b&#39;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#a6e22e\">component<\/span>: <span style=\"color:#66d9ef\">BComponent<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>    },\n<\/span><\/span><span style=\"display:flex;\"><span>    {\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#a6e22e\">path<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;c&#39;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#a6e22e\">component<\/span>: <span style=\"color:#66d9ef\">CComponent<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>    },\n<\/span><\/span><span style=\"display:flex;\"><span>  ]\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p>the <code>RouterOutlet<\/code>&rsquo;s contexts <code>Map<\/code> would look like this(roughly):<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span>{\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">primary<\/span><span style=\"color:#f92672\">:<\/span> { <span style=\"color:#75715e\">\/\/ Where `AComponent` resides [1]\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>    <span style=\"color:#a6e22e\">children<\/span><span style=\"color:#f92672\">:<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#75715e\">\/\/ Here `AComponent`&#39;s children reside [2]\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>      <span style=\"color:#a6e22e\">primary<\/span><span style=\"color:#f92672\">:<\/span> { <span style=\"color:#a6e22e\">children<\/span><span style=\"color:#f92672\">:<\/span> { <span style=\"color:#75715e\">\/* ... *\/<\/span> } }\n<\/span><\/span><span style=\"display:flex;\"><span>    }\n<\/span><\/span><span style=\"display:flex;\"><span>  }\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p>When a <code>RouterOutlet<\/code> is activated(it is about to render something), its <a href=\"https:\/\/github.com\/angular\/angular\/blob\/master\/packages\/router\/src\/directives\/router_outlet.ts#L132-L149\" target=\"_blank\" rel=\"noopener\"><code>activateWith<\/code><\/a> method will be called. We&rsquo;ve seen in the previous section that this is the place where the <code>OutletInjector<\/code> is created, which is what provides the scope for <code>ActivatedRoute<\/code>s:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">activateWith<\/span>(<span style=\"color:#a6e22e\">activatedRoute<\/span>: <span style=\"color:#66d9ef\">ActivatedRoute<\/span>, <span style=\"color:#a6e22e\">resolver<\/span>: <span style=\"color:#66d9ef\">ComponentFactoryResolver<\/span><span style=\"color:#f92672\">|<\/span><span style=\"color:#66d9ef\">null<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">isActivated<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">throw<\/span> <span style=\"color:#66d9ef\">new<\/span> Error(<span style=\"color:#e6db74\">&#39;Cannot activate an already activated outlet&#39;<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>  }\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">_activatedRoute<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">activatedRoute<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>    \n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#75715e\">\/* ... *\/<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">injector<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">new<\/span> <span style=\"color:#a6e22e\">OutletInjector<\/span>(<span style=\"color:#a6e22e\">activatedRoute<\/span>, <span style=\"color:#a6e22e\">childContexts<\/span>, <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">location<\/span>.<span style=\"color:#a6e22e\">injector<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">activated<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">location<\/span>.<span style=\"color:#a6e22e\">createComponent<\/span>(<span style=\"color:#a6e22e\">factory<\/span>, <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">location<\/span>.<span style=\"color:#a6e22e\">length<\/span>, <span style=\"color:#a6e22e\">injector<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p>Note that <code>this.activated<\/code> holds the <strong>routed component<\/strong>(e.g <code>AComponent<\/code>) and <code>this._activatedRoute<\/code> holds the <code>ActivatedRoute<\/code> for this component.<\/p>\n<p>Let&rsquo;s see now <a href=\"https:\/\/github.com\/angular\/angular\/blob\/master\/packages\/router\/src\/operators\/activate_routes.ts#L109-L126\" target=\"_blank\" rel=\"noopener\">what happens<\/a> when we&rsquo;re navigating to another route and the current view is destroyed:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">deactivateRouteAndOutlet<\/span>(\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">route<\/span>: <span style=\"color:#66d9ef\">TreeNode<\/span>&lt;<span style=\"color:#f92672\">ActivatedRoute<\/span>&gt;, <span style=\"color:#a6e22e\">parentContexts<\/span>: <span style=\"color:#66d9ef\">ChildrenOutletContexts<\/span>)<span style=\"color:#f92672\">:<\/span> <span style=\"color:#66d9ef\">void<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">context<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">parentContexts<\/span>.<span style=\"color:#a6e22e\">getContext<\/span>(<span style=\"color:#a6e22e\">route<\/span>.<span style=\"color:#a6e22e\">value<\/span>.<span style=\"color:#a6e22e\">outlet<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#a6e22e\">context<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">children<\/span><span style=\"color:#f92672\">:<\/span> {[<span style=\"color:#a6e22e\">outletName<\/span>: <span style=\"color:#66d9ef\">string<\/span>]<span style=\"color:#f92672\">:<\/span> <span style=\"color:#66d9ef\">any<\/span>} <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">nodeChildrenAsMap<\/span>(<span style=\"color:#a6e22e\">route<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>    \n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#75715e\">\/\/ from this we can also deduce that a component requires an additional `router-outlet` in this template\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>    <span style=\"color:#75715e\">\/\/ if it is part of route config. object where there is also a `children`\/`loadChildren` property\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>    <span style=\"color:#75715e\">\/\/ the `route`&#39;s `children` can also refer the routes obtained after loading a lazy module\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>    <span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">contexts<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">route<\/span>.<span style=\"color:#a6e22e\">value<\/span>.<span style=\"color:#a6e22e\">component<\/span> <span style=\"color:#f92672\">?<\/span> <span style=\"color:#a6e22e\">context.children<\/span> : <span style=\"color:#66d9ef\">parentContexts<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#75715e\">\/\/ Deactivate children first\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>    <span style=\"color:#a6e22e\">forEach<\/span>(<span style=\"color:#a6e22e\">children<\/span>, (<span style=\"color:#a6e22e\">v<\/span>: <span style=\"color:#66d9ef\">any<\/span>, <span style=\"color:#a6e22e\">k<\/span>: <span style=\"color:#66d9ef\">string<\/span>) <span style=\"color:#f92672\">=&gt;<\/span> <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">deactivateRouteAndItsChildren<\/span>(<span style=\"color:#a6e22e\">v<\/span>, <span style=\"color:#a6e22e\">contexts<\/span>));\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#a6e22e\">context<\/span>.<span style=\"color:#a6e22e\">outlet<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#75715e\">\/\/ Destroy the component\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>      <span style=\"color:#a6e22e\">context<\/span>.<span style=\"color:#a6e22e\">outlet<\/span>.<span style=\"color:#a6e22e\">deactivate<\/span>();\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#75715e\">\/\/ Destroy the contexts for all the outlets that were in the component\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>      <span style=\"color:#a6e22e\">context<\/span>.<span style=\"color:#a6e22e\">children<\/span>.<span style=\"color:#a6e22e\">onOutletDeactivated<\/span>();\n<\/span><\/span><span style=\"display:flex;\"><span>    }\n<\/span><\/span><span style=\"display:flex;\"><span>  }\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p>where <code>RouterOutlet.deactivate()<\/code> looks <a href=\"https:\/\/github.com\/angular\/angular\/blob\/master\/packages\/router\/src\/directives\/router_outlet.ts#L122-L130\" target=\"_blank\" rel=\"noopener\">like this<\/a>:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">deactivate<\/span>()<span style=\"color:#f92672\">:<\/span> <span style=\"color:#66d9ef\">void<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">activated<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">c<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">component<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">activated<\/span>.<span style=\"color:#a6e22e\">destroy<\/span>(); <span style=\"color:#75715e\">\/\/ Destroying the current component\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>    <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">activated<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">null<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#75715e\">\/\/ Nulling out the activated route - so no `complete` notification\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>    <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">_activatedRoute<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">null<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">deactivateEvents<\/span>.<span style=\"color:#a6e22e\">emit<\/span>(<span style=\"color:#a6e22e\">c<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>  }\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p>Notice that <code>this._activatedRoute = null;<\/code>, which means there is no need to unsubscribe from <code>ActivatedRoute<\/code>&rsquo;s observable properties. That&rsquo;s because these properties are <code>BehaviorSubject<\/code>s and, as we know, a <code>Subject<\/code> type maintains a list of subscribers. The memory leak may occur when the subscriber has not <em>removed itself<\/em> from the list(it can remote itself by using <code>subscriber.unsubscribe()<\/code>). But when the entity that holds everything(in this case the list of subscribers) is nulled out, it can be garbage collected, since it&rsquo;s no longer referenced, meaning that the subscriber which has not unsubscribed can non longer be invoked.<\/p>\n<h2 id=\"the-paramsinheritancestrategy-option\">\n  <span>\n  The <code>paramsInheritanceStrategy<\/code> option\n  <\/span>\n  <a href=\"#the-paramsinheritancestrategy-option\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><p>This option can be specified as part of the <code>ExtraOptions<\/code> object when calling <code>RouterModule.forRoot([], extraOptions)<\/code> and accepts 2 values: <code>'emptyOnly'<\/code>(default) or <code>'always'<\/code>. When using <code>'emptyOnly'<\/code>, what is does is to allow for <code>params<\/code> and <code>data<\/code> objects to be <em>inherited<\/em> from the parent route, if the current route(not necessarily the activated one) has <code>path: ''<\/code> or if the parent route is a componentless route.<\/p>\n<p>For instance, with such route configuration:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">routes<\/span>: <span style=\"color:#66d9ef\">Routes<\/span> <span style=\"color:#f92672\">=<\/span> [\n<\/span><\/span><span style=\"display:flex;\"><span>  {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">path<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#34;&#34;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">pathMatch<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#34;full&#34;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">component<\/span>: <span style=\"color:#66d9ef\">DefaultComponent<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>  },\n<\/span><\/span><span style=\"display:flex;\"><span>  {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">path<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#34;a\/:id&#34;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">data<\/span><span style=\"color:#f92672\">:<\/span> { <span style=\"color:#a6e22e\">one<\/span>: <span style=\"color:#66d9ef\">1<\/span> },\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">resolve<\/span><span style=\"color:#f92672\">:<\/span> { <span style=\"color:#a6e22e\">two<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#34;resolveTwo&#34;<\/span> },\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#75715e\">\/\/ component: AComponent,\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>    <span style=\"color:#a6e22e\">children<\/span><span style=\"color:#f92672\">:<\/span> [\n<\/span><\/span><span style=\"display:flex;\"><span>      { <span style=\"color:#a6e22e\">path<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#34;&#34;<\/span>, <span style=\"color:#a6e22e\">data<\/span><span style=\"color:#f92672\">:<\/span> { <span style=\"color:#a6e22e\">three<\/span>: <span style=\"color:#66d9ef\">3<\/span> }, <span style=\"color:#a6e22e\">component<\/span>: <span style=\"color:#66d9ef\">BComponent<\/span> },\n<\/span><\/span><span style=\"display:flex;\"><span>      {\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#a6e22e\">path<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#34;&#34;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#a6e22e\">data<\/span><span style=\"color:#f92672\">:<\/span> { <span style=\"color:#a6e22e\">four<\/span>: <span style=\"color:#66d9ef\">4<\/span> },\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#a6e22e\">resolve<\/span><span style=\"color:#f92672\">:<\/span> { <span style=\"color:#a6e22e\">five<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#34;resolveFive&#34;<\/span> },\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#a6e22e\">component<\/span>: <span style=\"color:#66d9ef\">CComponent<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#a6e22e\">outlet<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#34;named-c&#34;<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>      }\n<\/span><\/span><span style=\"display:flex;\"><span>    ]\n<\/span><\/span><span style=\"display:flex;\"><span>  }\n<\/span><\/span><span style=\"display:flex;\"><span>];\n<\/span><\/span><\/code><\/pre><\/div><p>if we navigate to <code>\/a\/123<\/code>, firstly, both <code>children<\/code> routes will be activated(because both have <code>path: ''<\/code>), then both of them will inherit the <code>data<\/code> and <code>params<\/code> object from their parent: <code>params: { id: 123, }<\/code>, <code>data: { one: 1, two: valueOfResolveTwo }<\/code>. Had we uncommented the <code>component: AComponent,<\/code> line, the results would be the same, since the condition for inheritance is for the route object to either have a componentless parent route, or the route itself to have the <code>path<\/code> set to <code>''<\/code>.<\/p>\n<p>You can see the above results and experiment further in this <a href=\"https:\/\/stackblitz.com\/edit\/exp-routing-paramsinheritance-sample-1?file=src%2Fapp%2Fapp.module.ts\" target=\"_blank\" rel=\"noopener\">StackBlitz demo<\/a>.<\/p>\n<p>Let&rsquo;s also examine a few other examples:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span>[\n<\/span><\/span><span style=\"display:flex;\"><span>  {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">path<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;a&#39;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">data<\/span><span style=\"color:#f92672\">:<\/span> { <span style=\"color:#a6e22e\">one<\/span>: <span style=\"color:#66d9ef\">1<\/span> },\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">children<\/span><span style=\"color:#f92672\">:<\/span> [ { <span style=\"color:#a6e22e\">path<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;b&#39;<\/span>, <span style=\"color:#a6e22e\">data<\/span><span style=\"color:#f92672\">:<\/span> { <span style=\"color:#a6e22e\">two<\/span>: <span style=\"color:#66d9ef\">2<\/span> }, <span style=\"color:#a6e22e\">component<\/span>: <span style=\"color:#66d9ef\">ComponentB<\/span> } ]\n<\/span><\/span><span style=\"display:flex;\"><span>  }\n<\/span><\/span><span style=\"display:flex;\"><span>]\n<\/span><\/span><\/code><\/pre><\/div><p>After navigating to <code>a\/b<\/code>, the <code>ComponentB<\/code>&rsquo;s <code>ActivatedRoute.data<\/code> will be <code>{one: 1, two: 2}<\/code>, because the parent <code>ActivatedRoute<\/code> belongs to a componentless route.<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span>[\n<\/span><\/span><span style=\"display:flex;\"><span>  {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">path<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;a&#39;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">component<\/span>: <span style=\"color:#66d9ef\">ComponentA<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">data<\/span><span style=\"color:#f92672\">:<\/span> { <span style=\"color:#a6e22e\">one<\/span>: <span style=\"color:#66d9ef\">1<\/span> },\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">children<\/span><span style=\"color:#f92672\">:<\/span> [ { <span style=\"color:#a6e22e\">path<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;b&#39;<\/span>, <span style=\"color:#a6e22e\">data<\/span><span style=\"color:#f92672\">:<\/span> { <span style=\"color:#a6e22e\">two<\/span>: <span style=\"color:#66d9ef\">2<\/span> }, <span style=\"color:#a6e22e\">component<\/span>: <span style=\"color:#66d9ef\">ComponentB<\/span> } ],\n<\/span><\/span><span style=\"display:flex;\"><span>  },\n<\/span><\/span><span style=\"display:flex;\"><span>]\n<\/span><\/span><\/code><\/pre><\/div><p>After navigating to <code>a\/b<\/code>, the <code>ComponentB<\/code>&rsquo;s <code>ActivatedRoute.data<\/code> will be <code>{ two: 2 }<\/code>, because neither the current <code>ActivatedRoute<\/code> belongs to a <code>path: ''<\/code> route, nor the parent <code>ActivatedRoute<\/code> belongs to a componentless route. Had we set <code>paramsInheritanceStrategy: 'always'<\/code>, we would get <code>{ one: 1, two: 2 }<\/code>.<\/p>\n<p>And lastly<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span>[\n<\/span><\/span><span style=\"display:flex;\"><span>  {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">path<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;foo\/:id&#39;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">children<\/span><span style=\"color:#f92672\">:<\/span> [\n<\/span><\/span><span style=\"display:flex;\"><span>      {\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#a6e22e\">path<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;a\/:name&#39;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#a6e22e\">children<\/span><span style=\"color:#f92672\">:<\/span> [\n<\/span><\/span><span style=\"display:flex;\"><span>          { \n<\/span><\/span><span style=\"display:flex;\"><span>            <span style=\"color:#a6e22e\">path<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;b&#39;<\/span>, \n<\/span><\/span><span style=\"display:flex;\"><span>            <span style=\"color:#a6e22e\">component<\/span>: <span style=\"color:#66d9ef\">ComponentB<\/span>, \n<\/span><\/span><span style=\"display:flex;\"><span>            <span style=\"color:#a6e22e\">children<\/span><span style=\"color:#f92672\">:<\/span> [ { <span style=\"color:#a6e22e\">path<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;c&#39;<\/span>, <span style=\"color:#a6e22e\">component<\/span>: <span style=\"color:#66d9ef\">ComponentC<\/span> } ]\n<\/span><\/span><span style=\"display:flex;\"><span>          }\n<\/span><\/span><span style=\"display:flex;\"><span>        ]\n<\/span><\/span><span style=\"display:flex;\"><span>      }\n<\/span><\/span><span style=\"display:flex;\"><span>    ]\n<\/span><\/span><span style=\"display:flex;\"><span>  }\n<\/span><\/span><span style=\"display:flex;\"><span>]\n<\/span><\/span><\/code><\/pre><\/div><p>After navigating to <code>foo\/123\/a\/andrei\/b\/c<\/code>, the <code>ComponentB<\/code>&rsquo;s <code>ActivatedRoute<\/code> will have the <code>params<\/code> set to <code>{ id: 123, name: 'andrei' }<\/code>(its parent belongs to a componentless route and the parent of its parent does the same), whereas the <code>ComponentC<\/code>&rsquo;s <code>ActivatedRoute<\/code> will have <code>params<\/code> set to <code>{}<\/code>, since the route it belongs to has <code>path: 'c'<\/code> and the parent <code>ActivatedRoute<\/code> does <em>not<\/em> belong to a componentless route.<\/p>\n<h2 id=\"the-queryparamshandling-option\">\n  <span>\n  The <code>queryParamsHandling<\/code> option\n  <\/span>\n  <a href=\"#the-queryparamshandling-option\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><p>This option can be specified as a property on <code>RouterLink<\/code> directive or <code>RouterLinkWithRef<\/code> directive and can accept two values: <code>'merge'<\/code> or <code>'preserve'<\/code>.<\/p>\n<p>All the examples can be found in this <a href=\"https:\/\/stackblitz.com\/edit\/exp-routing-queryparamshandling?file=src%2Fapp%2Fcomponents%2Fa.component.ts\" target=\"_blank\" rel=\"noopener\">StackBlitz demo<\/a>.<\/p>\n<p>There is also a nice tip that is related to this feature and this allows us to reuse the same view, without reloading the component, but with different <code>queryParams<\/code>:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-html\" data-lang=\"html\"><span style=\"display:flex;\"><span><span style=\"color:#75715e\">&lt;!-- assuming the current route has `k1=&#39;v1&#39;` --&gt;<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">&lt;!-- after clicking the button, the same component will be used(without being reloaded) --&gt;<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">&lt;!-- but the `queryParams` this time will be those written below --&gt;<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>&lt;<span style=\"color:#f92672\">button<\/span> <span style=\"color:#960050;background-color:#1e0010\">[<\/span><span style=\"color:#a6e22e\">queryParams<\/span><span style=\"color:#960050;background-color:#1e0010\">]=&#34;{<\/span> <span style=\"color:#a6e22e\">k2:<\/span> <span style=\"color:#960050;background-color:#1e0010\">&#39;<\/span><span style=\"color:#a6e22e\">v2<\/span><span style=\"color:#960050;background-color:#1e0010\">&#39;,<\/span> <span style=\"color:#a6e22e\">k1:<\/span> <span style=\"color:#960050;background-color:#1e0010\">&#39;<\/span><span style=\"color:#a6e22e\">foo-value-refreshed<\/span><span style=\"color:#960050;background-color:#1e0010\">&#39;<\/span> <span style=\"color:#960050;background-color:#1e0010\">}&#34;<\/span> <span style=\"color:#960050;background-color:#1e0010\">[<\/span><span style=\"color:#a6e22e\">routerLink<\/span><span style=\"color:#960050;background-color:#1e0010\">]=&#34;[]&#34;<\/span>&gt;...&lt;\/<span style=\"color:#f92672\">button<\/span>&gt;\n<\/span><\/span><\/code><\/pre><\/div><h2 id=\"how-to-specify-when-guards-and-resolvers-should-run\">\n  <span>\n  How to specify when guards and resolvers should run\n  <\/span>\n  <a href=\"#how-to-specify-when-guards-and-resolvers-should-run\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><p>One of the fascinating things about <code>@angular\/router<\/code> is the amount of features and customizations it provides us with. One of them is the <code>runGuardsAndResolvers<\/code> option, which can be used in the <code>Route<\/code> configuration object:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">export<\/span> <span style=\"color:#66d9ef\">type<\/span> <span style=\"color:#a6e22e\">RunGuardsAndResolvers<\/span> <span style=\"color:#f92672\">=<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#e6db74\">&#39;pathParamsChange&#39;<\/span><span style=\"color:#f92672\">|<\/span><span style=\"color:#e6db74\">&#39;pathParamsOrQueryParamsChange&#39;<\/span><span style=\"color:#f92672\">|<\/span><span style=\"color:#e6db74\">&#39;paramsChange&#39;<\/span><span style=\"color:#f92672\">|<\/span><span style=\"color:#e6db74\">&#39;paramsOrQueryParamsChange&#39;<\/span><span style=\"color:#f92672\">|<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#e6db74\">&#39;always&#39;<\/span><span style=\"color:#f92672\">|<\/span>((<span style=\"color:#66d9ef\">from<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#a6e22e\">ActivatedRouteSnapshot<\/span>, <span style=\"color:#a6e22e\">to<\/span>: <span style=\"color:#66d9ef\">ActivatedRouteSnapshot<\/span>) <span style=\"color:#f92672\">=&gt;<\/span> <span style=\"color:#66d9ef\">boolean<\/span>);\n<\/span><\/span><\/code><\/pre><\/div><p>Instead of using a StackBlitz application, this time we&rsquo;ll use some examples extracted from a few test cases. The route configuration will be this:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ runGuardsAndResolvers: RunGuardsAndResolvers = &#39;paramsChange&#39; (the default value)\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>[\n<\/span><\/span><span style=\"display:flex;\"><span>  {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">path<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;a&#39;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">runGuardsAndResolvers<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">component<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#75715e\">\/* ... *\/<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">canActivate<\/span><span style=\"color:#f92672\">:<\/span> [<span style=\"color:#e6db74\">&#39;guard&#39;<\/span>],\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">resolve<\/span><span style=\"color:#f92672\">:<\/span> {<span style=\"color:#a6e22e\">data<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;resolver&#39;<\/span>}\n<\/span><\/span><span style=\"display:flex;\"><span>  },\n<\/span><\/span><span style=\"display:flex;\"><span>]\n<\/span><\/span><\/code><\/pre><\/div><p>with the mention that <code>resolver<\/code> is simply a counter, which is incremented every time its function is invoked.<\/p>\n<p>Here are some examples, along with the logic that defines the test case:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">router<\/span>.<span style=\"color:#a6e22e\">navigateByUrl<\/span>(<span style=\"color:#e6db74\">&#39;\/a&#39;<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">cmp<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#75715e\">\/* ... *\/<\/span>; <span style=\"color:#75715e\">\/\/ the component associated with the `path: &#39;a&#39;` route\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span><span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">recordedData<\/span>: <span style=\"color:#66d9ef\">any<\/span>[] <span style=\"color:#f92672\">=<\/span> [];\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">cmp<\/span>.<span style=\"color:#a6e22e\">route<\/span>.<span style=\"color:#a6e22e\">data<\/span>.<span style=\"color:#a6e22e\">subscribe<\/span>((<span style=\"color:#a6e22e\">data<\/span>: <span style=\"color:#66d9ef\">any<\/span>) <span style=\"color:#f92672\">=&gt;<\/span> <span style=\"color:#a6e22e\">recordedData<\/span>.<span style=\"color:#a6e22e\">push<\/span>(<span style=\"color:#a6e22e\">data<\/span>)); <span style=\"color:#75715e\">\/\/ the values will be of type: `{ data: counterValue }`\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">runGuardsAndResolvers<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#e6db74\">`paramsChange`<\/span> <span style=\"color:#75715e\">\/\/ run guards &amp; resolvers when either `positional params` or `matrix params` change\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ since the first navigation already occurred, the resolver function was invoked once\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span><span style=\"color:#a6e22e\">expect<\/span>(<span style=\"color:#a6e22e\">recordedData<\/span>).<span style=\"color:#a6e22e\">toEqual<\/span>([{<span style=\"color:#a6e22e\">data<\/span>: <span style=\"color:#66d9ef\">0<\/span>}]);\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ although it&#39;s the same URL, the matrix params are different, so the guards and resolvers will be invoked once again\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span><span style=\"color:#a6e22e\">router<\/span>.<span style=\"color:#a6e22e\">navigateByUrl<\/span>(<span style=\"color:#e6db74\">&#39;\/a;p=1&#39;<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">expect<\/span>(<span style=\"color:#a6e22e\">recordedData<\/span>).<span style=\"color:#a6e22e\">toEqual<\/span>([{<span style=\"color:#a6e22e\">data<\/span>: <span style=\"color:#66d9ef\">0<\/span>}, {<span style=\"color:#a6e22e\">data<\/span>: <span style=\"color:#66d9ef\">1<\/span>}]);\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ same case the previous one\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span><span style=\"color:#a6e22e\">router<\/span>.<span style=\"color:#a6e22e\">navigateByUrl<\/span>(<span style=\"color:#e6db74\">&#39;\/a;p=2&#39;<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">expect<\/span>(<span style=\"color:#a6e22e\">recordedData<\/span>).<span style=\"color:#a6e22e\">toEqual<\/span>([{<span style=\"color:#a6e22e\">data<\/span>: <span style=\"color:#66d9ef\">0<\/span>}, {<span style=\"color:#a6e22e\">data<\/span>: <span style=\"color:#66d9ef\">1<\/span>}, {<span style=\"color:#a6e22e\">data<\/span>: <span style=\"color:#66d9ef\">2<\/span>}]);\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">router<\/span>.<span style=\"color:#a6e22e\">navigateByUrl<\/span>(<span style=\"color:#e6db74\">&#39;\/a;p=2?q=1&#39;<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ this time, nothing is changed, because only the `queryParams` have changed, but not the params\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ this would&#39;ve worked if `runGuardsAndResolvers` was set to `paramsOrQueryParamsChange`\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ so, `paramsOrQueryParamsChange` = `paramsChange` | `queryParamsChange`\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span><span style=\"color:#a6e22e\">expect<\/span>(<span style=\"color:#a6e22e\">recordedData<\/span>).<span style=\"color:#a6e22e\">toEqual<\/span>([{<span style=\"color:#a6e22e\">data<\/span>: <span style=\"color:#66d9ef\">0<\/span>}, {<span style=\"color:#a6e22e\">data<\/span>: <span style=\"color:#66d9ef\">1<\/span>}, {<span style=\"color:#a6e22e\">data<\/span>: <span style=\"color:#66d9ef\">2<\/span>}]);\n<\/span><\/span><\/code><\/pre><\/div><p>The <code>pathParamsChange<\/code> option might seem a bit confusing at first, but we might be able to clarify it a few examples:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ let&#39;s presume the counter has been reset \n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ run guards &amp; resolvers when only the positional params change\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ under the hood its just comparing the URLs of 2 `ActivatedRouteSnapshot` nodes that have the same route config. object\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span><span style=\"color:#a6e22e\">runGuardsAndResolvers<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#e6db74\">&#39;pathParamsChange&#39;<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">router<\/span>.<span style=\"color:#a6e22e\">navigateByUrl<\/span>(<span style=\"color:#e6db74\">&#39;\/a&#39;<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ `pathParamsChange` implies something like `a\/1 !== a\/2`\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ changing any optional(matrix) params will not result in running guards or resolvers\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span><span style=\"color:#a6e22e\">router<\/span>.<span style=\"color:#a6e22e\">navigateByUrl<\/span>(<span style=\"color:#e6db74\">&#39;\/a;p=1&#39;<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">expect<\/span>(<span style=\"color:#a6e22e\">recordedData<\/span>).<span style=\"color:#a6e22e\">toEqual<\/span>([{<span style=\"color:#a6e22e\">data<\/span>: <span style=\"color:#66d9ef\">0<\/span>}]);\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">router<\/span>.<span style=\"color:#a6e22e\">navigateByUrl<\/span>(<span style=\"color:#e6db74\">&#39;\/a;p=2&#39;<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">expect<\/span>(<span style=\"color:#a6e22e\">recordedData<\/span>).<span style=\"color:#a6e22e\">toEqual<\/span>([{<span style=\"color:#a6e22e\">data<\/span>: <span style=\"color:#66d9ef\">0<\/span>}]);\n<\/span><\/span><\/code><\/pre><\/div><p>Lastly, we have <code>pathParamsOrQueryParamsChange<\/code> which is the same as <code>pathParamsChange<\/code> from above, but it will also run the guards and the resolvers when <code>queryParams<\/code> change:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ let&#39;s presume the counter has been reset \n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">runGuardsAndResolvers<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#e6db74\">&#39;pathParamsOrQueryParamsChange&#39;<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">router<\/span>.<span style=\"color:#a6e22e\">navigateByUrl<\/span>(<span style=\"color:#e6db74\">&#39;\/a&#39;<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ changing matrix params will not result in running guards or resolvers\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span><span style=\"color:#a6e22e\">router<\/span>.<span style=\"color:#a6e22e\">navigateByUrl<\/span>(<span style=\"color:#e6db74\">&#39;\/a;p=1&#39;<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">expect<\/span>(<span style=\"color:#a6e22e\">recordedData<\/span>).<span style=\"color:#a6e22e\">toEqual<\/span>([{<span style=\"color:#a6e22e\">data<\/span>: <span style=\"color:#66d9ef\">0<\/span>}]);\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">router<\/span>.<span style=\"color:#a6e22e\">navigateByUrl<\/span>(<span style=\"color:#e6db74\">&#39;\/a;p=2&#39;<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">expect<\/span>(<span style=\"color:#a6e22e\">recordedData<\/span>).<span style=\"color:#a6e22e\">toEqual<\/span>([{<span style=\"color:#a6e22e\">data<\/span>: <span style=\"color:#66d9ef\">0<\/span>}]);\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ adding query params will re-run guards\/resolvers\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span><span style=\"color:#a6e22e\">router<\/span>.<span style=\"color:#a6e22e\">navigateByUrl<\/span>(<span style=\"color:#e6db74\">&#39;\/a;p=2?q=1&#39;<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">expect<\/span>(<span style=\"color:#a6e22e\">recordedData<\/span>).<span style=\"color:#a6e22e\">toEqual<\/span>([{<span style=\"color:#a6e22e\">data<\/span>: <span style=\"color:#66d9ef\">0<\/span>}, {<span style=\"color:#a6e22e\">data<\/span>: <span style=\"color:#66d9ef\">1<\/span>}]);\n<\/span><\/span><\/code><\/pre><\/div><h2 id=\"conclusion\">\n  <span>\n  Conclusion\n  <\/span>\n  <a href=\"#conclusion\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><p>In this article we went through many of the <code>@angular\/router<\/code>&rsquo;s useful features. I hope it was able to answer some questions you might have got about this package and shed a light on why it is so powerful.<\/p>\n<p><strong>Thanks for reading!<\/strong><\/p>\n"},{"title":"Demystifying angular\/router: what is `RouterScroller` and why is it useful ?","link":"https:\/\/andreigatej.dev\/blog\/angular-router-scroller\/","pubDate":"Tue, 06 Oct 2020 00:00:00 +0000","guid":"https:\/\/andreigatej.dev\/blog\/angular-router-scroller\/","description":"<p><em>This article has been published on <a href=\"https:\/\/indepth.dev\/posts\/1366\/demystifying-angular-router-what-is-routerscroller-and-why-is-it-useful-2\" target=\"_blank\" rel=\"noopener\">indepth.dev<\/a>.<\/em><\/p>\n<h2 id=\"introduction\">\n  <span>\n  Introduction\n  <\/span>\n  <a href=\"#introduction\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><p>The <code>RouterScroller<\/code> entity is a very interesting part of the Angular Router. In this post, we&rsquo;re going to have a look at how it works, what makes its features possible and how it can be configured, depending on the developer&rsquo;s needs.<\/p>\n<p>It helps us achieve things like scrolling to a fragment, setting an offset for that fragment and, lastly, navigating back to where the browser left off as a result of a <code>popstate<\/code> event.<\/p>\n<h2 id=\"how-routerscroller-is-set-up\">\n  <span>\n  How RouterScroller is set up\n  <\/span>\n  <a href=\"#how-routerscroller-is-set-up\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><p>Files referenced in this section: <a href=\"https:\/\/github.com\/angular\/angular\/blob\/master\/packages\/router\/src\/router_module.ts\" target=\"_blank\" rel=\"noopener\"><code>router_module<\/code><\/a>, <a href=\"https:\/\/github.com\/angular\/angular\/blob\/master\/packages\/router\/src\/router_scroller.ts\" target=\"_blank\" rel=\"noopener\"><code>router_scroller<\/code><\/a>.<\/p>\n<p>Since the <code>@angular\/router<\/code> is a built-in package provided by Angular, is has to go through a process of initialization, in order to make sure everything is set up correctly. In this case, it happens inside a <code>APP_BOOTSTRAP_LISTENER<\/code>&rsquo;s listener. If we peek at the source code, we can see that the first lines of the function&rsquo;s block are just <a href=\"https:\/\/github.com\/angular\/angular\/blob\/master\/packages\/router\/src\/router_module.ts#L549-L553\" target=\"_blank\" rel=\"noopener\"><code>this.injector.get<\/code> calls<\/a>:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">opts<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">injector<\/span>.<span style=\"color:#66d9ef\">get<\/span>(<span style=\"color:#a6e22e\">ROUTER_CONFIGURATION<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">preloader<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">injector<\/span>.<span style=\"color:#66d9ef\">get<\/span>(<span style=\"color:#a6e22e\">RouterPreloader<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">routerScroller<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">injector<\/span>.<span style=\"color:#66d9ef\">get<\/span>(<span style=\"color:#a6e22e\">RouterScroller<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">router<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">injector<\/span>.<span style=\"color:#66d9ef\">get<\/span>(<span style=\"color:#a6e22e\">Router<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">ref<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">injector<\/span>.<span style=\"color:#66d9ef\">get<\/span>&lt;<span style=\"color:#f92672\">ApplicationRef<\/span>&gt;(<span style=\"color:#a6e22e\">ApplicationRef<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/* ... *\/<\/span>\n<\/span><\/span><\/code><\/pre><\/div><p>This might seem trivial at first sight, but some of the arguments provided to <code>this.injector.get<\/code> are in fact <strong>factory tokens<\/strong>, meaning that some piece of logic will run in order to retrieve what has been asked for.<\/p>\n<p>For example, <code>RouterScroller<\/code>(the article&rsquo;s focal point) is defined as follows:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span>{\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">provide<\/span>: <span style=\"color:#66d9ef\">RouterScroller<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">useFactory<\/span>: <span style=\"color:#66d9ef\">createRouterScroller<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">deps<\/span><span style=\"color:#f92672\">:<\/span> [<span style=\"color:#a6e22e\">Router<\/span>, <span style=\"color:#a6e22e\">ViewportScroller<\/span>, <span style=\"color:#a6e22e\">ROUTER_CONFIGURATION<\/span>]\n<\/span><\/span><span style=\"display:flex;\"><span>},\n<\/span><\/span><\/code><\/pre><\/div><p><code>createRouterScroller<\/code> will simply create an instance of the <code>RouterScroller<\/code> class, based on the <code>ROUTER_CONFIGURATION<\/code> token. This can be seen in the class&rsquo; constructor:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">constructor<\/span>(\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">private<\/span> <span style=\"color:#a6e22e\">router<\/span>: <span style=\"color:#66d9ef\">Router<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">public<\/span> <span style=\"color:#66d9ef\">readonly<\/span> <span style=\"color:#a6e22e\">viewportScroller<\/span>: <span style=\"color:#66d9ef\">ViewportScroller<\/span>, <span style=\"color:#66d9ef\">private<\/span> <span style=\"color:#a6e22e\">options<\/span><span style=\"color:#f92672\">:<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#a6e22e\">scrollPositionRestoration<\/span><span style=\"color:#f92672\">?:<\/span> <span style=\"color:#e6db74\">&#39;disabled&#39;<\/span><span style=\"color:#f92672\">|<\/span><span style=\"color:#e6db74\">&#39;enabled&#39;<\/span><span style=\"color:#f92672\">|<\/span><span style=\"color:#e6db74\">&#39;top&#39;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#a6e22e\">anchorScrolling<\/span><span style=\"color:#f92672\">?:<\/span> <span style=\"color:#e6db74\">&#39;disabled&#39;<\/span><span style=\"color:#f92672\">|<\/span><span style=\"color:#e6db74\">&#39;enabled&#39;<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>    } <span style=\"color:#f92672\">=<\/span> {}) {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#75715e\">\/\/ Default both options to &#39;disabled&#39;\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>  <span style=\"color:#a6e22e\">options<\/span>.<span style=\"color:#a6e22e\">scrollPositionRestoration<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">options<\/span>.<span style=\"color:#a6e22e\">scrollPositionRestoration<\/span> <span style=\"color:#f92672\">||<\/span> <span style=\"color:#e6db74\">&#39;disabled&#39;<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">options<\/span>.<span style=\"color:#a6e22e\">anchorScrolling<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">options<\/span>.<span style=\"color:#a6e22e\">anchorScrolling<\/span> <span style=\"color:#f92672\">||<\/span> <span style=\"color:#e6db74\">&#39;disabled&#39;<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p>Then, after the <code>Router<\/code> is initialized (<code>Router.initialNavigation<\/code>), the <code>RouterScroller<\/code> will be initialized as well, with <code>RouterScroller.init()<\/code>:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">init<\/span>()<span style=\"color:#f92672\">:<\/span> <span style=\"color:#66d9ef\">void<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#75715e\">\/\/ we want to disable the automatic scrolling because having two places\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>  <span style=\"color:#75715e\">\/\/ responsible for scrolling results race conditions, especially given\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>  <span style=\"color:#75715e\">\/\/ that browser don&#39;t implement this behavior consistently\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>  <span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">options<\/span>.<span style=\"color:#a6e22e\">scrollPositionRestoration<\/span> <span style=\"color:#f92672\">!==<\/span> <span style=\"color:#e6db74\">&#39;disabled&#39;<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">viewportScroller<\/span>.<span style=\"color:#a6e22e\">setHistoryScrollRestoration<\/span>(<span style=\"color:#e6db74\">&#39;manual&#39;<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>  }\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">routerEventsSubscription<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">createScrollEvents<\/span>();\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">scrollEventsSubscription<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">consumeScrollEvents<\/span>();\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p>The last two lines represent the gist of <code>RouterScroller<\/code>. We are going to explore them in the following section, along with some examples.<\/p>\n<h2 id=\"how-routerscroller-works\">\n  <span>\n  How RouterScroller works\n  <\/span>\n  <a href=\"#how-routerscroller-works\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><p>Router events(e.g <code>NavigationStart<\/code>, <code>NavigationEnd<\/code>) play an important role in achieving <code>RouterScroller<\/code>&rsquo;s features. <code>Scroll<\/code> events are created based on specific Router events.<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">private<\/span> <span style=\"color:#a6e22e\">lastId<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#ae81ff\">0<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/* ... *\/<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">private<\/span> <span style=\"color:#a6e22e\">createScrollEvents() {<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">router<\/span>.<span style=\"color:#a6e22e\">events<\/span>.<span style=\"color:#a6e22e\">subscribe<\/span>(<span style=\"color:#a6e22e\">e<\/span> <span style=\"color:#f92672\">=&gt;<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#a6e22e\">e<\/span> <span style=\"color:#66d9ef\">instanceof<\/span> <span style=\"color:#a6e22e\">NavigationStart<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#75715e\">\/\/ store the scroll position of the current stable navigations.\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>      <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">store<\/span>[<span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">lastId<\/span>] <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">viewportScroller<\/span>.<span style=\"color:#a6e22e\">getScrollPosition<\/span>();\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">lastSource<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">e<\/span>.<span style=\"color:#a6e22e\">navigationTrigger<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">restoredId<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">e<\/span>.<span style=\"color:#a6e22e\">restoredState<\/span> <span style=\"color:#f92672\">?<\/span> <span style=\"color:#a6e22e\">e.restoredState.navigationId<\/span> : <span style=\"color:#66d9ef\">0<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>    } <span style=\"color:#66d9ef\">else<\/span> <span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#a6e22e\">e<\/span> <span style=\"color:#66d9ef\">instanceof<\/span> <span style=\"color:#a6e22e\">NavigationEnd<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">lastId<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">e<\/span>.<span style=\"color:#a6e22e\">id<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">scheduleScrollEvent<\/span>(<span style=\"color:#a6e22e\">e<\/span>, <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">router<\/span>.<span style=\"color:#a6e22e\">parseUrl<\/span>(<span style=\"color:#a6e22e\">e<\/span>.<span style=\"color:#a6e22e\">urlAfterRedirects<\/span>).<span style=\"color:#a6e22e\">fragment<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>    }\n<\/span><\/span><span style=\"display:flex;\"><span>  });\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p>The <code>browser<\/code> implementation of <code>ViewportScroller.getScrollPosition()<\/code> returns <code>[this.window.scrollX, this.window.scrollY];<\/code>, a tuple that describes the amount of pixels the document is scrolled horizontally and vertically. The <code>e.navigationTrigger<\/code> defines what trigger this navigation, which might be on of the three:<\/p>\n<ul>\n<li><code>'imperative'<\/code> - <em>manually<\/em> doing <code>router.navigate()<\/code> or <code>router.navigateByUrl()<\/code><\/li>\n<li><code>'popstate'<\/code> - clicking the <strong>forward<\/strong> or the <strong>back<\/strong> button, or <code>history.back()<\/code>\/<code>historyForward()<\/code><\/li>\n<li><code>'hashchange'<\/code>- when the <code>fragment<\/code> (the part prefixed with <code>#<\/code>) changes<\/li>\n<\/ul>\n<p><code>e.restoredState<\/code> is a very interesting part. Try to imagine the <strong>history stack<\/strong>. With every <code>history.pushState(stateObj, title, url)<\/code>, a <strong>new item<\/strong> is added to the browser&rsquo;s history stack. This is what essentially <em>concludes<\/em> a router navigation. Angular identifies every navigation with a <code>navigationId<\/code>(as you can see, it&rsquo;s useful for <code>this.restoredId<\/code> as well). The <code>navigationId<\/code> is assigned to a new navigation this way:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">id<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#f92672\">++<\/span><span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">navigationId<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ `setTransition` will push the object through the `Router stream` - a series of operators that have to deal with\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ determining the router configuration object, running the guards, setting the browser&#39;s URL etc...\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span><span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">setTransition<\/span>({\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">id<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">source<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">restoredState<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">currentUrlTree<\/span>: <span style=\"color:#66d9ef\">this.currentUrlTree<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">currentRawUrl<\/span>: <span style=\"color:#66d9ef\">this.rawUrlTree<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">rawUrl<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">extras<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">resolve<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">reject<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">promise<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">currentSnapshot<\/span>: <span style=\"color:#66d9ef\">this.routerState.snapshot<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">currentRouterState<\/span>: <span style=\"color:#66d9ef\">this.routerState<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>});\n<\/span><\/span><\/code><\/pre><\/div><p>When a <code>popstate<\/code> event occurs, the browser will move to the <strong>second uppermost<\/strong> item from the stack, which, as mentioned earlier, has a <code>navigationId<\/code> property in its state. That <code>navigationId<\/code> will be the <code>this.restoredId<\/code> in our case. So, <strong>two<\/strong> important things happen when the <code>NavigationStart<\/code> event occurs:<\/p>\n<ul>\n<li>we store the current position(<code>scrollX<\/code> and <code>scrollY<\/code>) of the document (with the help of <code>lastId<\/code>)<\/li>\n<li>we determine(if it exists) the <code>restoredId<\/code>, which is the <code>navigationId<\/code> of the <strong>previous navigation<\/strong>; notice that it is done only when the <code>popstate<\/code> event takes place<\/li>\n<\/ul>\n<p>Otherwise, if the <code>NavigationEnd<\/code> event occurs, only the current <code>navigationId<\/code> is stored: <code>this.lastId = e.id;<\/code> and a <code>Scroll<\/code> event is created:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">private<\/span> <span style=\"color:#a6e22e\">scheduleScrollEvent<\/span>(<span style=\"color:#a6e22e\">routerEvent<\/span>: <span style=\"color:#66d9ef\">NavigationEnd<\/span>, <span style=\"color:#a6e22e\">anchor<\/span>: <span style=\"color:#66d9ef\">string<\/span><span style=\"color:#f92672\">|<\/span><span style=\"color:#66d9ef\">null<\/span>)<span style=\"color:#f92672\">:<\/span> <span style=\"color:#66d9ef\">void<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#75715e\">\/\/ `router.triggerEvent` will push a new event(`routerEvent`) through the `router.events` stream\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>  <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">router<\/span>.<span style=\"color:#a6e22e\">triggerEvent<\/span>(<span style=\"color:#66d9ef\">new<\/span> <span style=\"color:#a6e22e\">Scroll<\/span>(\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#75715e\">\/\/ so, only if the `popstate` event occurred, the stored position will considered\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>      <span style=\"color:#75715e\">\/\/ otherwise, the position will be `null`\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>      <span style=\"color:#a6e22e\">routerEvent<\/span>, <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">lastSource<\/span> <span style=\"color:#f92672\">===<\/span> <span style=\"color:#e6db74\">&#39;popstate&#39;<\/span> <span style=\"color:#f92672\">?<\/span> <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">store<\/span>[<span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">restoredId<\/span>] <span style=\"color:#f92672\">:<\/span> <span style=\"color:#66d9ef\">null<\/span>, <span style=\"color:#a6e22e\">anchor<\/span>));\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p>Let&rsquo;s now see how the <code>Scroll<\/code> events are handled:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ from `init()` method\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span><span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">scrollEventsSubscription<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">consumeScrollEvents<\/span>();\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/* ... *\/<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">private<\/span> <span style=\"color:#a6e22e\">consumeScrollEvents() {<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">router<\/span>.<span style=\"color:#a6e22e\">events<\/span>.<span style=\"color:#a6e22e\">subscribe<\/span>(<span style=\"color:#a6e22e\">e<\/span> <span style=\"color:#f92672\">=&gt;<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#f92672\">!<\/span>(<span style=\"color:#a6e22e\">e<\/span> <span style=\"color:#66d9ef\">instanceof<\/span> <span style=\"color:#a6e22e\">Scroll<\/span>)) <span style=\"color:#66d9ef\">return<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>    \n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#75715e\">\/\/ a popstate event. The pop state event will always ignore anchor scrolling.\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>    <span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#a6e22e\">e<\/span>.<span style=\"color:#a6e22e\">position<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">options<\/span>.<span style=\"color:#a6e22e\">scrollPositionRestoration<\/span> <span style=\"color:#f92672\">===<\/span> <span style=\"color:#e6db74\">&#39;top&#39;<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">viewportScroller<\/span>.<span style=\"color:#a6e22e\">scrollToPosition<\/span>([<span style=\"color:#ae81ff\">0<\/span>, <span style=\"color:#ae81ff\">0<\/span>]);\n<\/span><\/span><span style=\"display:flex;\"><span>      } <span style=\"color:#66d9ef\">else<\/span> <span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">options<\/span>.<span style=\"color:#a6e22e\">scrollPositionRestoration<\/span> <span style=\"color:#f92672\">===<\/span> <span style=\"color:#e6db74\">&#39;enabled&#39;<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">viewportScroller<\/span>.<span style=\"color:#a6e22e\">scrollToPosition<\/span>(<span style=\"color:#a6e22e\">e<\/span>.<span style=\"color:#a6e22e\">position<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>      }\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#75715e\">\/\/ imperative navigation &#34;forward&#34;\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>    } <span style=\"color:#66d9ef\">else<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#a6e22e\">e<\/span>.<span style=\"color:#a6e22e\">anchor<\/span> <span style=\"color:#f92672\">&amp;&amp;<\/span> <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">options<\/span>.<span style=\"color:#a6e22e\">anchorScrolling<\/span> <span style=\"color:#f92672\">===<\/span> <span style=\"color:#e6db74\">&#39;enabled&#39;<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">viewportScroller<\/span>.<span style=\"color:#a6e22e\">scrollToAnchor<\/span>(<span style=\"color:#a6e22e\">e<\/span>.<span style=\"color:#a6e22e\">anchor<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>      } <span style=\"color:#66d9ef\">else<\/span> <span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">options<\/span>.<span style=\"color:#a6e22e\">scrollPositionRestoration<\/span> <span style=\"color:#f92672\">!==<\/span> <span style=\"color:#e6db74\">&#39;disabled&#39;<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">viewportScroller<\/span>.<span style=\"color:#a6e22e\">scrollToPosition<\/span>([<span style=\"color:#ae81ff\">0<\/span>, <span style=\"color:#ae81ff\">0<\/span>]);\n<\/span><\/span><span style=\"display:flex;\"><span>      }\n<\/span><\/span><span style=\"display:flex;\"><span>    }\n<\/span><\/span><span style=\"display:flex;\"><span>  });\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p>The <code>viewportScroller.scrollToPosition<\/code>, in a browser environment, is simply just: <code>this.window.scrollTo(position[0] \/* x *\/, position[1] \/* y *\/);<\/code> The logic in this handler can be influenced by some configuration options provided when instantiating the <code>RouterModule<\/code>(with <code>RouterModule.forRoot(routes, { \/* config *\/ })<\/code>). We&rsquo;ll discuss a couple of these options in the next section.<\/p>\n<p>But before going further, let&rsquo;s get a better understanding of what&rsquo;s going on by examining a common user flow.<\/p>\n<p><a href=\"https:\/\/ng-run.com\/edit\/NO8VpCY38E2eRVpIZi2w?open=app%2Fapp.module.ts\" target=\"_blank\" rel=\"noopener\">ng-run demo.<\/a><\/p>\n<p>Assuming the user would follow these steps:<\/p>\n<ul>\n<li>clicks on <code>go to default<\/code><\/li>\n<li>clicks on <code>go to default\/foo<\/code><\/li>\n<li>scrolls until <code>Test from foo - bottom 20%<\/code> is visible, as well as <code>go to default\/bar<\/code><\/li>\n<li>clicks on <code>go to default\/bar<\/code><\/li>\n<\/ul>\n<p>Now, if you click on <code>go back<\/code> button, you should now see the <code>Test from foo - bottom 20%<\/code> text:<\/p>\n<p><p class=\"markdown-image\">\n  <img src=\"images\/scroller-example.gif\" alt=\"Content image\"  \/>\n<\/p><\/p>\n<p>And here is how the flow could be visualized:<\/p>\n<p><p class=\"markdown-image\">\n  <img src=\"images\/routerscroller-state.jpg\" alt=\"Content image\"  \/>\n<\/p><\/p>\n<p><code>x{n}, y{n}<\/code> are the <code>scrollX<\/code> and <code>scrollY<\/code> values at a certain time when a new navigation is started.<\/p>\n<p>Now, after clicking on the <code>go back<\/code> button, the <code>RouterScroller<\/code>&rsquo;s state becomes:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span>{\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">restoredId<\/span>: <span style=\"color:#66d9ef\">2<\/span>, <span style=\"color:#75715e\">\/\/ `navigationId`\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>  <span style=\"color:#a6e22e\">lastId<\/span>: <span style=\"color:#66d9ef\">2<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#75715e\">\/* ... *\/<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p>And by using <code>store[restoredId]<\/code> we get the coordinates for the previous <code>\/default\/foo<\/code> view.<\/p>\n<p><em>Note: for this demo, the <code>scrollPositionRestoration<\/code> option has been used: <code>RouterModule.forRoot(routes, { scrollPositionRestoration: 'enabled' })<\/code><\/em><\/p>\n<h2 id=\"router-options-that-concern-routerscroller\">\n  <span>\n  Router options that concern RouterScroller\n  <\/span>\n  <a href=\"#router-options-that-concern-routerscroller\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><p>From the previous section we&rsquo;ve seen what the <code>scrollPositionRestoration<\/code> option does.<\/p>\n<p>Another 2 useful options are <code>anchorScrolling<\/code> and <code>scrollOffset<\/code>:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">private<\/span> <span style=\"color:#a6e22e\">consumeScrollEvents() {<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">router<\/span>.<span style=\"color:#a6e22e\">events<\/span>.<span style=\"color:#a6e22e\">subscribe<\/span>(<span style=\"color:#a6e22e\">e<\/span> <span style=\"color:#f92672\">=&gt;<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#f92672\">!<\/span>(<span style=\"color:#a6e22e\">e<\/span> <span style=\"color:#66d9ef\">instanceof<\/span> <span style=\"color:#a6e22e\">Scroll<\/span>)) <span style=\"color:#66d9ef\">return<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>    \n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#75715e\">\/\/ a popstate event. The pop state event will always ignore anchor scrolling.\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>    <span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#a6e22e\">e<\/span>.<span style=\"color:#a6e22e\">position<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">options<\/span>.<span style=\"color:#a6e22e\">scrollPositionRestoration<\/span> <span style=\"color:#f92672\">===<\/span> <span style=\"color:#e6db74\">&#39;top&#39;<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">viewportScroller<\/span>.<span style=\"color:#a6e22e\">scrollToPosition<\/span>([<span style=\"color:#ae81ff\">0<\/span>, <span style=\"color:#ae81ff\">0<\/span>]);\n<\/span><\/span><span style=\"display:flex;\"><span>      } <span style=\"color:#66d9ef\">else<\/span> <span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">options<\/span>.<span style=\"color:#a6e22e\">scrollPositionRestoration<\/span> <span style=\"color:#f92672\">===<\/span> <span style=\"color:#e6db74\">&#39;enabled&#39;<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">viewportScroller<\/span>.<span style=\"color:#a6e22e\">scrollToPosition<\/span>(<span style=\"color:#a6e22e\">e<\/span>.<span style=\"color:#a6e22e\">position<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>      }\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#75715e\">\/\/ imperative navigation &#34;forward&#34;\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>    } <span style=\"color:#66d9ef\">else<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#a6e22e\">e<\/span>.<span style=\"color:#a6e22e\">anchor<\/span> <span style=\"color:#f92672\">&amp;&amp;<\/span> <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">options<\/span>.<span style=\"color:#a6e22e\">anchorScrolling<\/span> <span style=\"color:#f92672\">===<\/span> <span style=\"color:#e6db74\">&#39;enabled&#39;<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">viewportScroller<\/span>.<span style=\"color:#a6e22e\">scrollToAnchor<\/span>(<span style=\"color:#a6e22e\">e<\/span>.<span style=\"color:#a6e22e\">anchor<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>      } <span style=\"color:#66d9ef\">else<\/span> <span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">options<\/span>.<span style=\"color:#a6e22e\">scrollPositionRestoration<\/span> <span style=\"color:#f92672\">!==<\/span> <span style=\"color:#e6db74\">&#39;disabled&#39;<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">viewportScroller<\/span>.<span style=\"color:#a6e22e\">scrollToPosition<\/span>([<span style=\"color:#ae81ff\">0<\/span>, <span style=\"color:#ae81ff\">0<\/span>]);\n<\/span><\/span><span style=\"display:flex;\"><span>      }\n<\/span><\/span><span style=\"display:flex;\"><span>    }\n<\/span><\/span><span style=\"display:flex;\"><span>  });\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p>As you can notice from the above snippet, by setting the <code>anchorScrolling<\/code> option to <code>enabled<\/code>, we can navigate to a particular element that belongs to the new view. The element can be recognized by settings its <code>id<\/code> attribute:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-html\" data-lang=\"html\"><span style=\"display:flex;\"><span>&lt;<span style=\"color:#f92672\">h4<\/span> <span style=\"color:#a6e22e\">id<\/span><span style=\"color:#f92672\">=<\/span><span style=\"color:#e6db74\">&#34;custom-fragment&#34;<\/span>&gt;<span style=\"color:#75715e\">&lt;!-- ... --&gt;<\/span>&lt;\/<span style=\"color:#f92672\">h4<\/span>&gt;\n<\/span><\/span><\/code><\/pre><\/div><p>and the navigation can be achieved with:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-html\" data-lang=\"html\"><span style=\"display:flex;\"><span>&lt;<span style=\"color:#f92672\">button<\/span> <span style=\"color:#a6e22e\">routerLink<\/span><span style=\"color:#f92672\">=<\/span><span style=\"color:#e6db74\">&#34;\/default\/foo&#34;<\/span> <span style=\"color:#a6e22e\">fragment<\/span><span style=\"color:#f92672\">=<\/span><span style=\"color:#e6db74\">&#34;custom-fragment&#34;<\/span>&gt;<span style=\"color:#75715e\">&lt;!-- ... --&gt;<\/span>&lt;\/<span style=\"color:#f92672\">button<\/span>&gt;\n<\/span><\/span><\/code><\/pre><\/div><p><a href=\"https:\/\/ng-run.com\/edit\/M0hEF4qn04ENateiUGjC?open=app%2Fapp.component.html\" target=\"_blank\" rel=\"noopener\">ng-run demo.<\/a><\/p>\n<p>Furthermore, when having <code>anchorScrolling<\/code> enabled, the <code>scrollOffset<\/code> option might be useful as well. You can play around with it by using: <code>RouterModule.forRoot(routes, { scrollOffset: [xOffset, yOffset] })<\/code>. To describe it briefly, imagine a Cartesian system xOy, where a coordinate Y is the point where the browser would normally scroll to if there were no offset specified. In fact, the default offset is 0. So, the <em>formula<\/em> would be: <code>finalOffsetY = Y + yOffset<\/code>. And the same goes for the <code>X<\/code> coordinate.<\/p>\n<h2 id=\"conclusion\">\n  <span>\n  Conclusion\n  <\/span>\n  <a href=\"#conclusion\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><p>The <code>RouterScroller<\/code> provides some essentials features of <code>angular\/router<\/code>. We&rsquo;ve examined how it is set up, the mechanisms that make everything possible and some of the ways it can be configured to suit certain needs.<\/p>\n<p><strong>Thank you for reading!<\/strong><\/p>\n"},{"title":"Angular Router: Getting to know UrlTree, ActivatedRouteSnapshot and ActivatedRoute Urltree Activatedroutesnapshot Activatedroute","link":"https:\/\/andreigatej.dev\/blog\/angular-urltree-activatedroutesnapshot-activatedroute\/","pubDate":"Sat, 03 Oct 2020 00:00:00 +0000","guid":"https:\/\/andreigatej.dev\/blog\/angular-urltree-activatedroutesnapshot-activatedroute\/","description":"<h1 id=\"introduction\">\n  <span>\n  Introduction\n  <\/span>\n  <a href=\"#introduction\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h1><p>In this part, we&rsquo;re going to cover why <code>UrlTree<\/code> is the foundation of a route transition and how <code>ActivatedRouteSnapshot<\/code> and <code>ActivatedRoute<\/code> provide a way to achieve features like <strong>guards<\/strong>, <strong>resolvers<\/strong>, or how an <code>ActivatedRoute<\/code> can be <em>updated<\/em>.<\/p>\n<h2 id=\"what-is-urlparser-and-why-it-is-important\">\n  <span>\n  What is UrlParser and why it is important\n  <\/span>\n  <a href=\"#what-is-urlparser-and-why-it-is-important\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><p><em>Note: You can find each example <a href=\"https:\/\/ng-run.com\/edit\/mzWif1S1fotcDGdwlnEA\" target=\"_blank\" rel=\"noopener\">here<\/a>.<\/em><\/p>\n<p>As we&rsquo;ll see in the following sections, a URL is a <strong>serialized<\/strong> version of a <code>UrlTree<\/code>. As a result, a <code>UrlTree<\/code> is the <strong>deserialized<\/strong> version of a <code>URL<\/code>.<\/p>\n<p>What a <code>UrlParser<\/code> does it to convert a URL into a <code>UrlTree<\/code> and it is primarily used by <code>DefaultUrlSerializer<\/code>. <code>DefaultUrlSerializer<\/code> is the default implementation of <code>UrlSerializer<\/code> and it&rsquo;s used, for instance, by <code>Router.parseUrl()<\/code> method:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-typescript\" data-lang=\"typescript\"><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">parseUrl<\/span>(<span style=\"color:#a6e22e\">url<\/span>: <span style=\"color:#66d9ef\">string<\/span>)<span style=\"color:#f92672\">:<\/span> <span style=\"color:#a6e22e\">UrlTree<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">let<\/span> <span style=\"color:#a6e22e\">urlTree<\/span>: <span style=\"color:#66d9ef\">UrlTree<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">try<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">urlTree<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">urlSerializer<\/span>.<span style=\"color:#a6e22e\">parse<\/span>(<span style=\"color:#a6e22e\">url<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>  } <span style=\"color:#66d9ef\">catch<\/span> (<span style=\"color:#a6e22e\">e<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">urlTree<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">malformedUriErrorHandler<\/span>(<span style=\"color:#a6e22e\">e<\/span>, <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">urlSerializer<\/span>, <span style=\"color:#a6e22e\">url<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>  }\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#a6e22e\">urlTree<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p>This also means that, if needed, we can use our <strong>custom<\/strong> implementation of <code>UrlSerializer<\/code>:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-typescript\" data-lang=\"typescript\"><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ In `providers` array\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>{ <span style=\"color:#a6e22e\">provide<\/span>: <span style=\"color:#66d9ef\">UrlSerializer<\/span>, <span style=\"color:#a6e22e\">useClass<\/span>: <span style=\"color:#66d9ef\">DefaultUrlSerializer<\/span> },\n<\/span><\/span><\/code><\/pre><\/div><p>An URL can have this structure: <code>segments?queryParams#fragment<\/code>; but, before diving into some examples, let&rsquo;s first define what are the main components of a <code>UrlTree<\/code>:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-typescript\" data-lang=\"typescript\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">export<\/span> <span style=\"color:#66d9ef\">class<\/span> <span style=\"color:#a6e22e\">UrlTree<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">constructor<\/span>(\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">public<\/span> <span style=\"color:#a6e22e\">root<\/span>: <span style=\"color:#66d9ef\">UrlSegmentGroup<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">public<\/span> <span style=\"color:#a6e22e\">queryParams<\/span>: <span style=\"color:#66d9ef\">Params<\/span>, <span style=\"color:#75715e\">\/\/ Params -&gt; {}\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>    <span style=\"color:#66d9ef\">public<\/span> <span style=\"color:#a6e22e\">fragment<\/span>: <span style=\"color:#66d9ef\">string<\/span><span style=\"color:#f92672\">|<\/span><span style=\"color:#66d9ef\">null<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>  ) { }\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#75715e\">\/* ... *\/<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p>From the aforementioned URL structure, we can already see that <code>queryParams<\/code> and <code>fragment<\/code> have found their pair. However, in which way does the <code>segments<\/code> part correspond with <code>UrlSegmentsGroup<\/code>?<\/p>\n<p>An example of a URL would be <code>a\/b\/c<\/code>. Here, we have no <em>explicit<\/em> groups, only two <em>implicit<\/em> groups and its <strong>segments<\/strong>(we&rsquo;ll see why a bit later). Groups are delimited by <code>()<\/code> and are very useful when we&rsquo;re dealing with multiple <strong>router outlets<\/strong>(e.g <strong>named<\/strong> outlets).<\/p>\n<p>Let&rsquo;s see the structure of a <code>UrlSegmentGroup<\/code>:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-typescript\" data-lang=\"typescript\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">export<\/span> <span style=\"color:#66d9ef\">class<\/span> <span style=\"color:#a6e22e\">UrlSegmentGroup<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">parent<\/span>: <span style=\"color:#66d9ef\">UrlSegmentGroup<\/span><span style=\"color:#f92672\">|<\/span><span style=\"color:#66d9ef\">null<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">null<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">constructor<\/span>(\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">public<\/span> <span style=\"color:#a6e22e\">segments<\/span>: <span style=\"color:#66d9ef\">UrlSegment<\/span>[],\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">public<\/span> <span style=\"color:#a6e22e\">children<\/span><span style=\"color:#f92672\">:<\/span> {[<span style=\"color:#a6e22e\">key<\/span>: <span style=\"color:#66d9ef\">string<\/span>]<span style=\"color:#f92672\">:<\/span> <span style=\"color:#a6e22e\">UrlSegmentGroup<\/span>}\n<\/span><\/span><span style=\"display:flex;\"><span>  ) { }\n<\/span><\/span><\/code><\/pre><\/div><p>As stated earlier, there are 2 <em>implicit<\/em> groups. The first one is the <strong>root<\/strong> <code>UrlSegmentGroup<\/code>, which does not have any segments, only one child <code>UrlSegmentGroup<\/code>. The reason behind this is that it should correspond to the root of the component tree, e.g <code>AppComponent<\/code>, which is inherently not included in any route configuration. As we&rsquo;ll discover in the next articles from this series, the way Angular resolves route transitions is based on traversing the <code>UrlTree<\/code>, while taking into account the <code>Routes<\/code> configuration. The second <code>UrlSegmentGroup<\/code>, whose parent is the first one, is the one that actually contains the segments. We&rsquo;ll see how a <code>UrlSegment<\/code> looks in a minute.<\/p>\n<p>We might have a more complex URL, such as <code>foo\/123\/(a\/\/named:b)<\/code>. The resulted <code>UrlSegmentGroup<\/code> will be this:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-typescript\" data-lang=\"typescript\"><span style=\"display:flex;\"><span>{\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">segments<\/span><span style=\"color:#f92672\">:<\/span> [], <span style=\"color:#75715e\">\/\/ The root UrlSegmentGroup never has any segments\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>  <span style=\"color:#a6e22e\">children<\/span><span style=\"color:#f92672\">:<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">primary<\/span><span style=\"color:#f92672\">:<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#a6e22e\">segments<\/span><span style=\"color:#f92672\">:<\/span> [{ <span style=\"color:#a6e22e\">path<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;foo&#39;<\/span>, <span style=\"color:#a6e22e\">parameters<\/span><span style=\"color:#f92672\">:<\/span> {} }, { <span style=\"color:#a6e22e\">path<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;123&#39;<\/span>, <span style=\"color:#a6e22e\">parameters<\/span><span style=\"color:#f92672\">:<\/span> {} }],\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#a6e22e\">children<\/span><span style=\"color:#f92672\">:<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#a6e22e\">primary<\/span><span style=\"color:#f92672\">:<\/span> { <span style=\"color:#a6e22e\">segments<\/span><span style=\"color:#f92672\">:<\/span> [{ <span style=\"color:#a6e22e\">path<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;a&#39;<\/span>, <span style=\"color:#a6e22e\">parameters<\/span><span style=\"color:#f92672\">:<\/span> {} }], <span style=\"color:#a6e22e\">children<\/span><span style=\"color:#f92672\">:<\/span> {} },\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#a6e22e\">named<\/span><span style=\"color:#f92672\">:<\/span> { <span style=\"color:#a6e22e\">segments<\/span><span style=\"color:#f92672\">:<\/span> [{ <span style=\"color:#a6e22e\">path<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;b&#39;<\/span>, <span style=\"color:#a6e22e\">parameters<\/span><span style=\"color:#f92672\">:<\/span> {} }], <span style=\"color:#a6e22e\">children<\/span><span style=\"color:#f92672\">:<\/span> {} },\n<\/span><\/span><span style=\"display:flex;\"><span>      },\n<\/span><\/span><span style=\"display:flex;\"><span>    },\n<\/span><\/span><span style=\"display:flex;\"><span>  },\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p>which would match a route configuration like this:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-typescript\" data-lang=\"typescript\"><span style=\"display:flex;\"><span>{\n<\/span><\/span><span style=\"display:flex;\"><span>  {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">path<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;foo\/:id&#39;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">loadChildren<\/span><span style=\"color:#f92672\">:<\/span> () <span style=\"color:#f92672\">=&gt;<\/span> <span style=\"color:#66d9ef\">import<\/span>(<span style=\"color:#e6db74\">&#39;.\/foo\/foo.module&#39;<\/span>).<span style=\"color:#a6e22e\">then<\/span>(<span style=\"color:#a6e22e\">m<\/span> <span style=\"color:#f92672\">=&gt;<\/span> <span style=\"color:#a6e22e\">m<\/span>.<span style=\"color:#a6e22e\">FooModule<\/span>)\n<\/span><\/span><span style=\"display:flex;\"><span>  },\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#75715e\">\/\/ foo.module.ts\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>  {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">path<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;a&#39;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">component<\/span>: <span style=\"color:#66d9ef\">AComponent<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  },\n<\/span><\/span><span style=\"display:flex;\"><span>  {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">path<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;b&#39;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">component<\/span>: <span style=\"color:#66d9ef\">BComponent<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">outlet<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;named&#39;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  },\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p><em>You can experiment with this example in this <a href=\"https:\/\/stackblitz.com\/edit\/routing-base-url-parser?file=src%2Fapp%2Ffoo%2Ffoo.module.ts\" target=\"_blank\" rel=\"noopener\">StackBlitz<\/a>.<\/em><\/p>\n<p>As seen from above, <code>UrlSegmentGroup<\/code>&rsquo;s children are delimited by <code>()<\/code>. The names of these children are the <strong>router outlet<\/strong>.<\/p>\n<p>In <code>\/(a\/\/named:b)<\/code>, because it uses a <code>\/<\/code> before <code>(<\/code>(the could also be <code>x\/y\/z(foo:path)<\/code>), <code>a<\/code> will be segment of the <strong>primary outlet<\/strong>. <code>\/\/<\/code> is the separator for router outlets. Finally, <code>named:b<\/code> follows this structure: <code>outletName:segmentPath<\/code>.<\/p>\n<p>Another thing that should be mentioned is the <code>UrlSegment<\/code>&rsquo;s <code>parameters<\/code> property:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-typescript\" data-lang=\"typescript\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">export<\/span> <span style=\"color:#66d9ef\">class<\/span> <span style=\"color:#a6e22e\">UrlSegment<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">constructor<\/span>(\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">public<\/span> <span style=\"color:#a6e22e\">path<\/span>: <span style=\"color:#66d9ef\">string<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#75715e\">\/** The matrix parameters associated with a segment *\/<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">public<\/span> <span style=\"color:#a6e22e\">parameters<\/span><span style=\"color:#f92672\">:<\/span> {[<span style=\"color:#a6e22e\">name<\/span>: <span style=\"color:#66d9ef\">string<\/span>]<span style=\"color:#f92672\">:<\/span> <span style=\"color:#66d9ef\">string<\/span>}) {}\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p>Besides <strong>positional parameters<\/strong>(e.g <code>foo\/:a\/:b<\/code>), segments can have parameters declared like this: <code>segment\/path;k1=v1;k2=v2<\/code>.<\/p>\n<p>So, a <code>UrlTree<\/code> can be summarized in: the <code>root<\/code> <code>UrlSegmentGroup<\/code>, the <code>queryParams<\/code> object and the <code>fragment<\/code> of the issued URL.<\/p>\n<h3 id=\"what-is-the-difference-between--and-\">\n  <span>\n  What is the difference between <code>\/()<\/code> and <code>()<\/code>?\n  <\/span>\n  <a href=\"#what-is-the-difference-between--and-\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h3><p>Let&rsquo;s begin with a question, what URL would match such configuration?<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-typescript\" data-lang=\"typescript\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">routes<\/span> <span style=\"color:#f92672\">=<\/span> [\n<\/span><\/span><span style=\"display:flex;\"><span>  {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">path<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;foo&#39;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">component<\/span>: <span style=\"color:#66d9ef\">FooComponent<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  },\n<\/span><\/span><span style=\"display:flex;\"><span>  {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">path<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;bar&#39;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">component<\/span>: <span style=\"color:#66d9ef\">BarComponent<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">outlet<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;special&#39;<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>  }\n<\/span><\/span><span style=\"display:flex;\"><span>]\n<\/span><\/span><\/code><\/pre><\/div><p><em>You can find a working example <a href=\"https:\/\/ng-run.com\/edit\/dszYKzt8Azuai9VNaUsD\" target=\"_blank\" rel=\"noopener\">here<\/a>.<\/em><\/p>\n<p>It&rsquo;s worth mentioning that in this entire process of resolving the <em>next<\/em> route, the routes array will be iterated over once for each <code>UrlSegmentGroup<\/code> child at a certain level. This applies to the nested arrays too(e.g <code>children<\/code>, <code>loadChildren<\/code>).<\/p>\n<p>So, a URL that matches the above configuration would be: <code>foo(special:bar)<\/code>. This is because the root <code>UrlSegmentGroup<\/code>&rsquo;s child <code>UrlSegmentGroup<\/code>s are:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-typescript\" data-lang=\"typescript\"><span style=\"display:flex;\"><span>{\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#75715e\">\/\/ root&#39;s children\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">primary<\/span><span style=\"color:#f92672\">:<\/span> { <span style=\"color:#a6e22e\">segments<\/span><span style=\"color:#f92672\">:<\/span> [{ <span style=\"color:#a6e22e\">path<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;foo&#39;<\/span>, <span style=\"color:#75715e\">\/* ... *\/<\/span> }], <span style=\"color:#a6e22e\">children<\/span><span style=\"color:#f92672\">:<\/span> {} },\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">special<\/span><span style=\"color:#f92672\">:<\/span> { <span style=\"color:#a6e22e\">segments<\/span><span style=\"color:#f92672\">:<\/span> [{ <span style=\"color:#a6e22e\">path<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;bar&#39;<\/span>, <span style=\"color:#75715e\">\/* ... *\/<\/span> }], <span style=\"color:#a6e22e\">children<\/span><span style=\"color:#f92672\">:<\/span> {} },\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p>As specified before, for each child(in this case <code>primary<\/code> and <code>special<\/code>) it will try to find a match in the <code>routes<\/code> array.<br>\nIf the URL was <code>foo\/(special:bar)<\/code>, then the root <code>UrlSegmentGroup<\/code> would have only one child:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-typescript\" data-lang=\"typescript\"><span style=\"display:flex;\"><span>{\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#75715e\">\/\/ root child\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">primary<\/span><span style=\"color:#f92672\">:<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">segments<\/span><span style=\"color:#f92672\">:<\/span> [{ <span style=\"color:#a6e22e\">path<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;foo&#39;<\/span>, <span style=\"color:#75715e\">\/* ... *\/<\/span> }],\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">children<\/span><span style=\"color:#f92672\">:<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#a6e22e\">special<\/span><span style=\"color:#f92672\">:<\/span> { <span style=\"color:#a6e22e\">segments<\/span><span style=\"color:#f92672\">:<\/span> [{ <span style=\"color:#a6e22e\">path<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;bar&#39;<\/span>, <span style=\"color:#75715e\">\/* ... *\/<\/span> }], <span style=\"color:#a6e22e\">children<\/span><span style=\"color:#f92672\">:<\/span> {} }\n<\/span><\/span><span style=\"display:flex;\"><span>    }\n<\/span><\/span><span style=\"display:flex;\"><span>  }\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p>Which would match this configuration:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-typescript\" data-lang=\"typescript\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">routes<\/span>: <span style=\"color:#66d9ef\">Routes<\/span> <span style=\"color:#f92672\">=<\/span> [\n<\/span><\/span><span style=\"display:flex;\"><span>  {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">path<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;foo&#39;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">component<\/span>: <span style=\"color:#66d9ef\">FooComponent<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">children<\/span><span style=\"color:#f92672\">:<\/span> [\n<\/span><\/span><span style=\"display:flex;\"><span>      {\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#a6e22e\">path<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;bar&#39;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#a6e22e\">component<\/span>: <span style=\"color:#66d9ef\">BarComponent<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#a6e22e\">outlet<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;special&#39;<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>      }\n<\/span><\/span><span style=\"display:flex;\"><span>    ],\n<\/span><\/span><span style=\"display:flex;\"><span>  },\n<\/span><\/span><span style=\"display:flex;\"><span>];\n<\/span><\/span><\/code><\/pre><\/div><p><em>You can find a working example <a href=\"https:\/\/ng-run.com\/edit\/S2lkjjUkVpbM6z5RCHjs?open=app%2Fapp.module.ts\" target=\"_blank\" rel=\"noopener\">here<\/a>.<\/em><\/p>\n<p>Additionally, along the <code>special<\/code> <code>UrlSegmentGroup<\/code>, you can have another primary <code>UrlSegmentGroup<\/code>: <code>foo\/(a\/path\/primary\/\/special:bar)<\/code>. Note that <code>a\/path\/primary<\/code> is <em>automatically<\/em> assigned to a <code>primary<\/code> <code>UrlSegmentGroup<\/code> child only if the <code>\/()<\/code> syntax is used.<\/p>\n<h3 id=\"exercises\">\n  <span>\n  Exercises\n  <\/span>\n  <a href=\"#exercises\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h3><p>In this section, we&rsquo;re going to go over some exercises in order to get a better understanding of how the <code>UrlParser<\/code> works.<\/p>\n<p><strong>What URL would match with this configuration ? (to match all of them)<\/strong><\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-typescript\" data-lang=\"typescript\"><span style=\"display:flex;\"><span>[\n<\/span><\/span><span style=\"display:flex;\"><span>  {<span style=\"color:#a6e22e\">path<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;a&#39;<\/span>, <span style=\"color:#a6e22e\">component<\/span>: <span style=\"color:#66d9ef\">ComponentA<\/span>},\n<\/span><\/span><span style=\"display:flex;\"><span>  {<span style=\"color:#a6e22e\">path<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;b&#39;<\/span>, <span style=\"color:#a6e22e\">component<\/span>: <span style=\"color:#66d9ef\">ComponentB<\/span>, <span style=\"color:#a6e22e\">outlet<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;left&#39;<\/span>},\n<\/span><\/span><span style=\"display:flex;\"><span>  {<span style=\"color:#a6e22e\">path<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;c&#39;<\/span>, <span style=\"color:#a6e22e\">component<\/span>: <span style=\"color:#66d9ef\">ComponentC<\/span>, <span style=\"color:#a6e22e\">outlet<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;right&#39;<\/span>}\n<\/span><\/span><span style=\"display:flex;\"><span>],\n<\/span><\/span><\/code><\/pre><\/div><details>\n  <summary>Solution<\/summary>\n  <p><code>a(left:b\/\/right:c)<\/code><\/p>\n<p>The root <code>UrlSegmentGroup<\/code>&rsquo;s children are:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-typescript\" data-lang=\"typescript\"><span style=\"display:flex;\"><span>{\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">primary<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;a&#39;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">left<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;b&#39;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">right<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;c&#39;<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div>\n<\/details>\n<p><strong>What would the <code>UrlTree<\/code> look like is this case?<\/strong><\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">console<\/span>.<span style=\"color:#a6e22e\">log<\/span>(<span style=\"color:#a6e22e\">r<\/span>.<span style=\"color:#a6e22e\">parseUrl<\/span>(<span style=\"color:#e6db74\">&#39;\/q\/(a\/(c\/\/left:cp)\/\/left:qp)(left:ap)&#39;<\/span>))\n<\/span><\/span><\/code><\/pre><\/div><details>\n  <summary>Solution<\/summary>\n  <div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-typescript\" data-lang=\"typescript\"><span style=\"display:flex;\"><span>{\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#75715e\">\/\/ root&#39;s children\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#75715e\">\/\/ #1\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>  <span style=\"color:#a6e22e\">primary<\/span><span style=\"color:#f92672\">:<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">segments<\/span><span style=\"color:#f92672\">:<\/span> [<span style=\"color:#e6db74\">&#39;q&#39;<\/span>],\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">children<\/span><span style=\"color:#f92672\">:<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#75715e\">\/\/ #2\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>      <span style=\"color:#a6e22e\">primary<\/span><span style=\"color:#f92672\">:<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#a6e22e\">segments<\/span><span style=\"color:#f92672\">:<\/span> [<span style=\"color:#e6db74\">&#39;a&#39;<\/span>],\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#a6e22e\">children<\/span><span style=\"color:#f92672\">:<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>          <span style=\"color:#75715e\">\/\/ #3\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>          <span style=\"color:#a6e22e\">primary<\/span><span style=\"color:#f92672\">:<\/span> { <span style=\"color:#a6e22e\">segments<\/span><span style=\"color:#f92672\">:<\/span> [<span style=\"color:#e6db74\">&#39;c&#39;<\/span>] },\n<\/span><\/span><span style=\"display:flex;\"><span>          <span style=\"color:#a6e22e\">left<\/span><span style=\"color:#f92672\">:<\/span> { <span style=\"color:#a6e22e\">segments<\/span><span style=\"color:#f92672\">:<\/span> [<span style=\"color:#e6db74\">&#39;cp&#39;<\/span>] }\n<\/span><\/span><span style=\"display:flex;\"><span>        }\n<\/span><\/span><span style=\"display:flex;\"><span>      },\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#a6e22e\">left<\/span><span style=\"color:#f92672\">:<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#a6e22e\">segments<\/span><span style=\"color:#f92672\">:<\/span> [<span style=\"color:#e6db74\">&#39;qp&#39;<\/span>]\n<\/span><\/span><span style=\"display:flex;\"><span>      }\n<\/span><\/span><span style=\"display:flex;\"><span>    }\n<\/span><\/span><span style=\"display:flex;\"><span>  },\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">left<\/span><span style=\"color:#f92672\">:<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">segments<\/span><span style=\"color:#f92672\">:<\/span> [<span style=\"color:#e6db74\">&#39;ap&#39;<\/span>]\n<\/span><\/span><span style=\"display:flex;\"><span>  }\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p><em>You can find this example <a href=\"https:\/\/ng-run.com\/edit\/mzWif1S1fotcDGdwlnEA\" target=\"_blank\" rel=\"noopener\">here<\/a> as well.<\/em><\/p>\n<ul>\n<li><code>\/q\/(...)(left:ap)<\/code>: <code>#1<\/code><\/li>\n<li><code>\/q\/(a\/(...)\/\/left:qp)...<\/code>: <code>#2<\/code><\/li>\n<li><code>\/q\/(a\/(c\/\/left:cp)\/\/...)...<\/code>: <code>#3<\/code><\/li>\n<\/ul>\n<\/details>\n<h2 id=\"urltree-activatedroutesnapshot-and-activatedroute\">\n  <span>\n  UrlTree, ActivatedRouteSnapshot and ActivatedRoute\n  <\/span>\n  <a href=\"#urltree-activatedroutesnapshot-and-activatedroute\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><p>As we&rsquo;ve seen from the previous section, a <code>UrlTree<\/code> contains the <code>fragment<\/code>, <code>queryParams<\/code> and the <code>UrlSegmentGroup<\/code>s that create the URL segments. At the same time, there are other important units that make up the process of resolving the next route: <code>ActivatedRouteSnapshot<\/code> and <code>ActivatedRoute<\/code>. This process also consists of multiple <strong>phrases<\/strong>, e.g: running guards, running resolvers, activating the routes(i.e updating the view accordingly); these phases will operate on 2 other <em>tree structures<\/em>: a tree of <code>ActivatedRouteSnapshot<\/code>s(also named <code>RouterStateSnapshot<\/code>) and a tree of <code>ActivatedRoute<\/code>s(also named <code>RouterState<\/code>).<\/p>\n<p>The <code>ActivatedRouteSnapshot<\/code> tree will be immediately created after the <code>UrlTree<\/code> has been built. One significant difference between these two tree structures is that in a <code>UrlTree<\/code> only outlets(named or <code>primary<\/code>, by default) are considered children(child = <code>UrlSegmentGroup<\/code>), whereas in <code>RouterStateSnapshot<\/code>, each matched path of a <code>Route<\/code> object determines an <code>ActivatedRouteSnapshot<\/code> child.<\/p>\n<p>Let&rsquo;s see an example. For this route configuration:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-typescript\" data-lang=\"typescript\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">routes<\/span>: <span style=\"color:#66d9ef\">Routes<\/span> <span style=\"color:#f92672\">=<\/span> [\n<\/span><\/span><span style=\"display:flex;\"><span>  {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">path<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;foo&#39;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">component<\/span>: <span style=\"color:#66d9ef\">FooComponent<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">children<\/span><span style=\"color:#f92672\">:<\/span> [\n<\/span><\/span><span style=\"display:flex;\"><span>      {\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#a6e22e\">path<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;bar&#39;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#a6e22e\">component<\/span>: <span style=\"color:#66d9ef\">BarComponent<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#a6e22e\">outlet<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;special&#39;<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>      }\n<\/span><\/span><span style=\"display:flex;\"><span>    ],\n<\/span><\/span><span style=\"display:flex;\"><span>  },\n<\/span><\/span><span style=\"display:flex;\"><span>];\n<\/span><\/span><\/code><\/pre><\/div><p>and the next URL <code>foo\/(special:bar)<\/code>, the <code>ActivatedRouteSnapshot<\/code> tree would look like this:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-typescript\" data-lang=\"typescript\"><span style=\"display:flex;\"><span>{\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#75715e\">\/\/ root\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>  <span style=\"color:#a6e22e\">url<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;foo\/(special:bar)&#39;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">outlet<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;primary&#39;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#75715e\">\/* ... *\/<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">children<\/span><span style=\"color:#f92672\">:<\/span> [\n<\/span><\/span><span style=\"display:flex;\"><span>    {\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#a6e22e\">url<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;foo&#39;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#a6e22e\">outlet<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;primary&#39;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#75715e\">\/* ... *\/<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#a6e22e\">children<\/span><span style=\"color:#f92672\">:<\/span> [\n<\/span><\/span><span style=\"display:flex;\"><span>        { <span style=\"color:#a6e22e\">url<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;bar&#39;<\/span>, <span style=\"color:#a6e22e\">outlet<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;special&#39;<\/span>, <span style=\"color:#a6e22e\">children<\/span><span style=\"color:#f92672\">:<\/span> [], <span style=\"color:#75715e\">\/* ... *\/<\/span> }\n<\/span><\/span><span style=\"display:flex;\"><span>      ]\n<\/span><\/span><span style=\"display:flex;\"><span>    }\n<\/span><\/span><span style=\"display:flex;\"><span>  ]\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p>This tree is constructed by iterating through the route configuration array, while also using the previously created <code>UrlTree<\/code>. For example,<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-typescript\" data-lang=\"typescript\"><span style=\"display:flex;\"><span>{\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">path<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;foo&#39;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">component<\/span>: <span style=\"color:#66d9ef\">FooComponent<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">children<\/span><span style=\"color:#f92672\">:<\/span> [<span style=\"color:#75715e\">\/* ... *\/<\/span>],\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p>will match with this <code>UrlSegmentGroup<\/code>:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-typescript\" data-lang=\"typescript\"><span style=\"display:flex;\"><span>{\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">segments<\/span><span style=\"color:#f92672\">:<\/span> [{ <span style=\"color:#a6e22e\">path<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;foo&#39;<\/span> }]\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">children<\/span><span style=\"color:#f92672\">:<\/span> { <span style=\"color:#a6e22e\">special<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#75715e\">\/* ... *\/<\/span> }\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p>Then, the resulted <code>ActivatedRouteSnapshot<\/code> from above will have a child <code>ActivatedRouteSnapshot<\/code>, because the <strong>matched path<\/strong>(i.e <code>foo<\/code>) belongs to a route configuration object which also has the <code>children<\/code> property(the same would&rsquo;ve happened if there was <code>loadChildren<\/code>).<\/p>\n<p>Based on the <code>RouterStateSnapshot<\/code>, Angular will determine which guards and which resolvers should run, and also how to create the <code>ActivatedRoute<\/code> tree. <code>RouterState<\/code> will essentially have the same structure as <code>RouterStateSnapshot<\/code>, except that, instead of <code>ActivatedRouteSnapshot<\/code> nodes, it will contain <code>ActivatedRoute<\/code> nodes. This step is necessary because the developer has the opportunity to opt for a custom <code>RouteReuseStrategy<\/code>, which is a way to <em>store<\/em> a subtree of <code>ActivatedRouteSnapshot<\/code> nodes and can be useful if we don&rsquo;t want do recreate components if the same navigation occurs multiple times.<\/p>\n<p>Furthermore, we can also highlight the difference between <code>ActivatedRoute<\/code> and <code>ActivatedRouteSnapshot<\/code>. The <code>ActivatedRouteSnapshot<\/code> tree will always be <strong>recreated<\/strong>(from the <code>UrlTree<\/code>), but some nodes of the <code>ActivatedRoute<\/code> tree can be <strong>reused<\/strong>, which explains how it&rsquo;s possible to be notified, for example, when <strong>positional params<\/strong>(e.g <code>foo\/:id\/:param<\/code>) change, by subscribing to <code>ActivatedRoute<\/code>&rsquo;s observable properties(<code>params<\/code>, <code>data<\/code>, <code>queryParams<\/code>, <code>url<\/code> etc&hellip;).<br>\nThis is achieved by comparing the current <code>RouterState<\/code>(before the navigation) and the next <code>RouterState<\/code>(after the navigation). An <code>ActivatedRoute<\/code> node can be reused if <code>current.routeConfig === next.routeConfig<\/code>, where <code>routeConfig<\/code> is the object we place inside the <code>routes<\/code> array.<\/p>\n<p>To illustrate that, let&rsquo;s consider this route configuration:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-typescript\" data-lang=\"typescript\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">routes<\/span>: <span style=\"color:#66d9ef\">Routes<\/span> <span style=\"color:#f92672\">=<\/span> [\n<\/span><\/span><span style=\"display:flex;\"><span>  {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">path<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;empty\/:id&#39;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">component<\/span>: <span style=\"color:#66d9ef\">EmptyComponent<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">children<\/span><span style=\"color:#f92672\">:<\/span> [\n<\/span><\/span><span style=\"display:flex;\"><span>      {\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#a6e22e\">path<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;foo&#39;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#a6e22e\">component<\/span>: <span style=\"color:#66d9ef\">FooComponent<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>      },\n<\/span><\/span><span style=\"display:flex;\"><span>      {\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#a6e22e\">path<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;bar&#39;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#a6e22e\">component<\/span>: <span style=\"color:#66d9ef\">BarComponent<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#a6e22e\">outlet<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;special&#39;<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>      },\n<\/span><\/span><span style=\"display:flex;\"><span>      {\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#a6e22e\">path<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;beer&#39;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#a6e22e\">component<\/span>: <span style=\"color:#66d9ef\">BeerComponent<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#a6e22e\">outlet<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;special&#39;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>      },\n<\/span><\/span><span style=\"display:flex;\"><span>    ]\n<\/span><\/span><span style=\"display:flex;\"><span>  }\n<\/span><\/span><span style=\"display:flex;\"><span>];\n<\/span><\/span><\/code><\/pre><\/div><p>and this initial issued URL: <code>'empty\/123\/(foo\/\/special:bar)'<\/code>. If we would now navigate to <code>empty\/999\/(foo\/\/special:beer)<\/code>, then we could visualize the comparison between <code>RouterState<\/code> trees like this:<\/p>\n<!-- raw HTML omitted -->\n<p>As you can see, the <code>Empty<\/code> node(which corresponds to <code>path: 'empty\/:id'<\/code>) is reused, because this expression evaluates to <code>true<\/code>: <code>current.routeConfig === next.routeConfig<\/code>, where <code>routeConfig<\/code> is:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-typescript\" data-lang=\"typescript\"><span style=\"display:flex;\"><span>{\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">path<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;empty\/:id&#39;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">children<\/span><span style=\"color:#f92672\">:<\/span> [<span style=\"color:#75715e\">\/* ... *\/<\/span>]\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p>We can also see these lines from <code>EmptyComponent<\/code>:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-typescript\" data-lang=\"typescript\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">export<\/span> <span style=\"color:#66d9ef\">class<\/span> <span style=\"color:#a6e22e\">EmptyComponent<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">constructor<\/span> (<span style=\"color:#a6e22e\">activatedRoute<\/span>: <span style=\"color:#66d9ef\">ActivatedRoute<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">console<\/span>.<span style=\"color:#a6e22e\">warn<\/span>(<span style=\"color:#e6db74\">&#39;[EmptyComponent]: constructor&#39;<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">activatedRoute<\/span>.<span style=\"color:#a6e22e\">params<\/span>.<span style=\"color:#a6e22e\">subscribe<\/span>(<span style=\"color:#a6e22e\">console<\/span>.<span style=\"color:#a6e22e\">log<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>  }\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p>and also from clicking these buttons:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-html\" data-lang=\"html\"><span style=\"display:flex;\"><span>&lt;<span style=\"color:#f92672\">button<\/span> <span style=\"color:#960050;background-color:#1e0010\">(<\/span><span style=\"color:#a6e22e\">click<\/span><span style=\"color:#960050;background-color:#1e0010\">)=&#34;<\/span><span style=\"color:#a6e22e\">router<\/span><span style=\"color:#960050;background-color:#1e0010\">.<\/span><span style=\"color:#a6e22e\">navigateByUrl<\/span><span style=\"color:#960050;background-color:#1e0010\">(&#39;<\/span><span style=\"color:#a6e22e\">empty<\/span><span style=\"color:#960050;background-color:#1e0010\">\/<\/span><span style=\"color:#a6e22e\">123<\/span><span style=\"color:#960050;background-color:#1e0010\">\/(<\/span><span style=\"color:#a6e22e\">foo<\/span><span style=\"color:#960050;background-color:#1e0010\">\/\/<\/span><span style=\"color:#a6e22e\">special:bar<\/span><span style=\"color:#960050;background-color:#1e0010\">)&#39;)&#34;<\/span>&gt;empty\/123\/(foo\/\/special:bar)&lt;\/<span style=\"color:#f92672\">button<\/span>&gt;\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>&lt;<span style=\"color:#f92672\">br<\/span>&gt;&lt;<span style=\"color:#f92672\">br<\/span>&gt;\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>&lt;<span style=\"color:#f92672\">button<\/span> <span style=\"color:#960050;background-color:#1e0010\">(<\/span><span style=\"color:#a6e22e\">click<\/span><span style=\"color:#960050;background-color:#1e0010\">)=&#34;<\/span><span style=\"color:#a6e22e\">router<\/span><span style=\"color:#960050;background-color:#1e0010\">.<\/span><span style=\"color:#a6e22e\">navigateByUrl<\/span><span style=\"color:#960050;background-color:#1e0010\">(&#39;<\/span><span style=\"color:#a6e22e\">empty<\/span><span style=\"color:#960050;background-color:#1e0010\">\/<\/span><span style=\"color:#a6e22e\">999<\/span><span style=\"color:#960050;background-color:#1e0010\">\/(<\/span><span style=\"color:#a6e22e\">foo<\/span><span style=\"color:#960050;background-color:#1e0010\">\/\/<\/span><span style=\"color:#a6e22e\">special:beer<\/span><span style=\"color:#960050;background-color:#1e0010\">)&#39;)&#34;<\/span>&gt;empty\/123\/(foo\/\/special:beer)&lt;\/<span style=\"color:#f92672\">button<\/span>&gt;\n<\/span><\/span><\/code><\/pre><\/div><p>The same logic can be applied for each of <code>ActivatedRoute<\/code>&rsquo;s observable properties:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-typescript\" data-lang=\"typescript\"><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">url<\/span>: <span style=\"color:#66d9ef\">Observable<\/span>&lt;<span style=\"color:#f92672\">UrlSegment<\/span><span style=\"color:#960050;background-color:#1e0010\">[]<\/span>&gt;,\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/** An observable of the matrix parameters scoped to this route. *\/<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">params<\/span>: <span style=\"color:#66d9ef\">Observable<\/span>&lt;<span style=\"color:#f92672\">Params<\/span>&gt;,\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/** An observable of the query parameters shared by all the routes. *\/<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">queryParams<\/span>: <span style=\"color:#66d9ef\">Observable<\/span>&lt;<span style=\"color:#f92672\">Params<\/span>&gt;,\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/** An observable of the URL fragment shared by all the routes. *\/<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">fragment<\/span>: <span style=\"color:#66d9ef\">Observable<\/span>&lt;<span style=\"color:#f92672\">string<\/span>&gt;,\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/** An observable of the static and resolved data of this route. *\/<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">data<\/span>: <span style=\"color:#66d9ef\">Observable<\/span>&lt;<span style=\"color:#f92672\">Data<\/span>&gt;,\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/**\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"> * An Observable that contains a map of the required and optional parameters\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">  * specific to the route.\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">  * The map supports retrieving single and multiple values from the same parameter.\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">  *\/<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">get<\/span> <span style=\"color:#a6e22e\">paramMap<\/span>()<span style=\"color:#f92672\">:<\/span> <span style=\"color:#a6e22e\">Observable<\/span>&lt;<span style=\"color:#f92672\">ParamMap<\/span>&gt; {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#f92672\">!<\/span><span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">_paramMap<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">_paramMap<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">params<\/span>.<span style=\"color:#a6e22e\">pipe<\/span>(<span style=\"color:#a6e22e\">map<\/span>((<span style=\"color:#a6e22e\">p<\/span>: <span style=\"color:#66d9ef\">Params<\/span>)<span style=\"color:#f92672\">:<\/span> <span style=\"color:#a6e22e\">ParamMap<\/span> <span style=\"color:#f92672\">=&gt;<\/span> <span style=\"color:#a6e22e\">convertToParamMap<\/span>(<span style=\"color:#a6e22e\">p<\/span>)));\n<\/span><\/span><span style=\"display:flex;\"><span>  }\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">_paramMap<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/**\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"> * An Observable that contains a map of the query parameters available to all routes.\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"> * The map supports retrieving single and multiple values from the query parameter.\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"> *\/<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">get<\/span> <span style=\"color:#a6e22e\">queryParamMap<\/span>()<span style=\"color:#f92672\">:<\/span> <span style=\"color:#a6e22e\">Observable<\/span>&lt;<span style=\"color:#f92672\">ParamMap<\/span>&gt; {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#f92672\">!<\/span><span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">_queryParamMap<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">_queryParamMap<\/span> <span style=\"color:#f92672\">=<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">queryParams<\/span>.<span style=\"color:#a6e22e\">pipe<\/span>(<span style=\"color:#a6e22e\">map<\/span>((<span style=\"color:#a6e22e\">p<\/span>: <span style=\"color:#66d9ef\">Params<\/span>)<span style=\"color:#f92672\">:<\/span> <span style=\"color:#a6e22e\">ParamMap<\/span> <span style=\"color:#f92672\">=&gt;<\/span> <span style=\"color:#a6e22e\">convertToParamMap<\/span>(<span style=\"color:#a6e22e\">p<\/span>)));\n<\/span><\/span><span style=\"display:flex;\"><span>  }\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">_queryParamMap<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p><em>A working example can be found <a href=\"https:\/\/ng-run.com\/edit\/45kL9ml80w1K8i81EzTk?open=app%2Fapp.component.html\" target=\"_blank\" rel=\"noopener\">here<\/a>.<\/em><\/p>\n<h2 id=\"when-is-urltree-used-\">\n  <span>\n  When is UrlTree used ?\n  <\/span>\n  <a href=\"#when-is-urltree-used-\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><p>Now that we&rsquo;ve understood what a <code>UrlTree<\/code> is, we can explore a few use cases.<\/p>\n<h3 id=\"when-a-urltree-is-returned-from-a-guard-it-will-result-in-a-redirect-operation\">\n  <span>\n  When a <code>UrlTree<\/code> is returned from a guard, it will result in a redirect operation\n  <\/span>\n  <a href=\"#when-a-urltree-is-returned-from-a-guard-it-will-result-in-a-redirect-operation\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h3><p>As we can see from the <a href=\"https:\/\/github.com\/angular\/angular\/blob\/master\/packages\/router\/src\/router.ts#L617-L625\" target=\"_blank\" rel=\"noopener\">source code<\/a>:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-typescript\" data-lang=\"typescript\"><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/* \n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">if `canActivate` returns `UrlTree` -&gt; redirect\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">*\/<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">checkGuards<\/span>(<span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">ngModule<\/span>.<span style=\"color:#a6e22e\">injector<\/span>, (<span style=\"color:#a6e22e\">evt<\/span>: <span style=\"color:#66d9ef\">Event<\/span>) <span style=\"color:#f92672\">=&gt;<\/span> <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">triggerEvent<\/span>(<span style=\"color:#a6e22e\">evt<\/span>)),\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">tap<\/span>(<span style=\"color:#a6e22e\">t<\/span> <span style=\"color:#f92672\">=&gt;<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#a6e22e\">isUrlTree<\/span>(<span style=\"color:#a6e22e\">t<\/span>.<span style=\"color:#a6e22e\">guardsResult<\/span>)) {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">error<\/span>: <span style=\"color:#66d9ef\">Error<\/span><span style=\"color:#f92672\">&amp;<\/span>{<span style=\"color:#a6e22e\">url?<\/span>: <span style=\"color:#66d9ef\">UrlTree<\/span>} <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">navigationCancelingError<\/span>(\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#e6db74\">`Redirecting to &#34;<\/span><span style=\"color:#e6db74\">${<\/span><span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">serializeUrl<\/span>(<span style=\"color:#a6e22e\">t<\/span>.<span style=\"color:#a6e22e\">guardsResult<\/span>)<span style=\"color:#e6db74\">}<\/span><span style=\"color:#e6db74\">&#34;`<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">error<\/span>.<span style=\"color:#a6e22e\">url<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">t<\/span>.<span style=\"color:#a6e22e\">guardsResult<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">throw<\/span> <span style=\"color:#a6e22e\">error<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>  }\n<\/span><\/span><span style=\"display:flex;\"><span>})\n<\/span><\/span><\/code><\/pre><\/div><p>For example:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-typescript\" data-lang=\"typescript\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">routes<\/span> <span style=\"color:#f92672\">=<\/span> [\n<\/span><\/span><span style=\"display:flex;\"><span>  {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">path<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;foo\/:id&#39;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">component<\/span>: <span style=\"color:#66d9ef\">FooComponent<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">canActivate<\/span><span style=\"color:#f92672\">:<\/span> [<span style=\"color:#e6db74\">&#39;fooGuard&#39;<\/span>]\n<\/span><\/span><span style=\"display:flex;\"><span>  },\n<\/span><\/span><span style=\"display:flex;\"><span>  {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">path<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;bar&#39;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">component<\/span>: <span style=\"color:#66d9ef\">BarComponent<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>  }\n<\/span><\/span><span style=\"display:flex;\"><span>];\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ `providers` array\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>[\n<\/span><\/span><span style=\"display:flex;\"><span>  {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">provide<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;fooGuard&#39;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>    \n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#75715e\">\/\/ `futureARS` - future `ActivatedRouteSnapshot`\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>    <span style=\"color:#a6e22e\">useFactory<\/span><span style=\"color:#f92672\">:<\/span> (<span style=\"color:#a6e22e\">router<\/span>: <span style=\"color:#66d9ef\">Router<\/span>) <span style=\"color:#f92672\">=&gt;<\/span> (<span style=\"color:#a6e22e\">futureARS<\/span>) <span style=\"color:#f92672\">=&gt;<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#f92672\">+<\/span><span style=\"color:#a6e22e\">futureARS<\/span>.<span style=\"color:#a6e22e\">paramMap<\/span>.<span style=\"color:#66d9ef\">get<\/span>(<span style=\"color:#e6db74\">&#39;id&#39;<\/span>) <span style=\"color:#f92672\">===<\/span> <span style=\"color:#ae81ff\">1<\/span> <span style=\"color:#f92672\">?<\/span> <span style=\"color:#a6e22e\">router<\/span>.<span style=\"color:#a6e22e\">parseUrl<\/span>(<span style=\"color:#e6db74\">&#39;\/bar&#39;<\/span>) <span style=\"color:#f92672\">:<\/span> <span style=\"color:#66d9ef\">true<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>    },\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">deps<\/span><span style=\"color:#f92672\">:<\/span> [<span style=\"color:#a6e22e\">Router<\/span>]\n<\/span><\/span><span style=\"display:flex;\"><span>  },\n<\/span><\/span><span style=\"display:flex;\"><span>]\n<\/span><\/span><\/code><\/pre><\/div><p><em>An example can be found <a href=\"https:\/\/ng-run.com\/edit\/0MKTWXshcBEd49BH1be7?open=app%2Fapp.module.ts\" target=\"_blank\" rel=\"noopener\">here<\/a>.<\/em><\/p>\n<h3 id=\"routernavigatebyurl\">\n  <span>\n  <code>Router.navigateByUrl()<\/code>\n  <\/span>\n  <a href=\"#routernavigatebyurl\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h3><p>The <a href=\"https:\/\/github.com\/angular\/angular\/blob\/master\/packages\/router\/src\/router.ts#L1080-L1091\" target=\"_blank\" rel=\"noopener\"><code>Router.navigateByUrl(url)<\/code><\/a> method converts the provided <code>url<\/code> into a <code>UrlTree<\/code>:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-typescript\" data-lang=\"typescript\"><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">navigateByUrl<\/span>(<span style=\"color:#a6e22e\">url<\/span>: <span style=\"color:#66d9ef\">string<\/span><span style=\"color:#f92672\">|<\/span><span style=\"color:#a6e22e\">UrlTree<\/span>, <span style=\"color:#a6e22e\">extras<\/span>: <span style=\"color:#66d9ef\">NavigationExtras<\/span> <span style=\"color:#f92672\">=<\/span> {<span style=\"color:#a6e22e\">skipLocationChange<\/span>: <span style=\"color:#66d9ef\">false<\/span>})<span style=\"color:#f92672\">:<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">Promise<\/span>&lt;<span style=\"color:#f92672\">boolean<\/span>&gt; {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#75715e\">\/* ... *\/<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#75715e\">\/\/ `parseUrl` -&gt; create `UrlTree`\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>  <span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">urlTree<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">isUrlTree<\/span>(<span style=\"color:#a6e22e\">url<\/span>) <span style=\"color:#f92672\">?<\/span> <span style=\"color:#a6e22e\">url<\/span> : <span style=\"color:#66d9ef\">this.parseUrl<\/span>(<span style=\"color:#a6e22e\">url<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">mergedTree<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">urlHandlingStrategy<\/span>.<span style=\"color:#a6e22e\">merge<\/span>(<span style=\"color:#a6e22e\">urlTree<\/span>, <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">rawUrlTree<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">scheduleNavigation<\/span>(<span style=\"color:#a6e22e\">mergedTree<\/span>, <span style=\"color:#e6db74\">&#39;imperative&#39;<\/span>, <span style=\"color:#66d9ef\">null<\/span>, <span style=\"color:#a6e22e\">extras<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><h3 id=\"router-directives\">\n  <span>\n  Router Directives\n  <\/span>\n  <a href=\"#router-directives\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h3><p><code>RouterLink<\/code> and <code>RouterLinkActive<\/code> rely on <code>UrlTree<\/code>s in order to achieve their functionality.<\/p>\n<p><code>RouterLinkActive<\/code> will compare the current <code>UrlTree<\/code> with the one resulted from <code>RouterLink<\/code>&rsquo;s commands and, based on the results, will add\/remove classes accordingly.<\/p>\n<p><code>RouterLink<\/code> will create a new <code>UrlTree<\/code>, based on the current <code>UrlTree<\/code> and the provided commands.<\/p>\n<!-- raw HTML omitted -->\n<p>We will explore them in detail in future articles, as they are pretty complex.<\/p>\n<p><strong>Thanks for reading!<\/strong><\/p>\n"},{"title":"Angular Forms: Why is ngModelChange late when updating ngModel value","link":"https:\/\/andreigatej.dev\/blog\/angular-forms-ngmodelchange-late\/","pubDate":"Wed, 16 Sep 2020 00:00:00 +0000","guid":"https:\/\/andreigatej.dev\/blog\/angular-forms-ngmodelchange-late\/","description":"<p><em>This article has been published on <a href=\"https:\/\/indepth.dev\/posts\/1331\/angular-forms-why-is-ngmodelchange-late-when-updating-ngmodel-value\" target=\"_blank\" rel=\"noopener\">indepth.dev<\/a>.<\/em><\/p>\n<h2 id=\"introduction\">\n  <span>\n  Introduction\n  <\/span>\n  <a href=\"#introduction\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><p>The <code>@angular\/forms<\/code> package is rich in functionalities and although is widely used, it still has some unsolved mysteries. The aim of this article is to clarify why the problem in question occurs and how it can be solved. This involves strong familiarity with Angular Forms, so it would be preferable to read <a href=\"https:\/\/indepth.dev\/a-thorough-exploration-of-angular-forms\/\" target=\"_blank\" rel=\"noopener\">A thorough exploration of Angular Forms<\/a> first, but not mandatory, as I will cover the necessary concepts once again in the following sections.<\/p>\n<p><em>This article has been inspired by this <a href=\"https:\/\/stackoverflow.com\/q\/63667435\/9632621\" target=\"_blank\" rel=\"noopener\">Stack Overflow question<\/a>.<\/em><\/p>\n<h2 id=\"the-problem\">\n  <span>\n  The problem\n  <\/span>\n  <a href=\"#the-problem\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><p>Let&rsquo;s say we want to create a directive which will perform some changes on what the user types into an input, so that the bound <code>FormControl<\/code> will have the altered value.<\/p>\n<p>Our directive may look like this:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">@Directive<\/span>({\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">selector<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;[myDirective]&#39;<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>})\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">export<\/span> <span style=\"color:#66d9ef\">class<\/span> <span style=\"color:#a6e22e\">Mydirective<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">constructor<\/span>(<span style=\"color:#66d9ef\">private<\/span> <span style=\"color:#a6e22e\">control<\/span>: <span style=\"color:#66d9ef\">NgControl<\/span>) { }\n<\/span><\/span><span style=\"display:flex;\"><span>  \n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">processInput<\/span>(<span style=\"color:#a6e22e\">value<\/span>: <span style=\"color:#66d9ef\">any<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#a6e22e\">value<\/span>.<span style=\"color:#a6e22e\">toUpperCase<\/span>();\n<\/span><\/span><span style=\"display:flex;\"><span>  }\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">@HostListener<\/span>(<span style=\"color:#e6db74\">&#39;ngModelChange&#39;<\/span>, [<span style=\"color:#e6db74\">&#39;$event&#39;<\/span>])\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">ngModelChange<\/span>(<span style=\"color:#a6e22e\">value<\/span>: <span style=\"color:#66d9ef\">any<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">control<\/span>.<span style=\"color:#a6e22e\">valueAccessor<\/span>.<span style=\"color:#a6e22e\">writeValue<\/span>(<span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">processInput<\/span>(<span style=\"color:#a6e22e\">value<\/span>));\n<\/span><\/span><span style=\"display:flex;\"><span>  }\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p>and could be used like this:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span>&lt;<span style=\"color:#f92672\">hello<\/span> <span style=\"color:#a6e22e\">name<\/span><span style=\"color:#f92672\">=<\/span><span style=\"color:#e6db74\">&#34;{{ name }}&#34;<\/span>&gt;&lt;\/<span style=\"color:#f92672\">hello<\/span>&gt;\n<\/span><\/span><span style=\"display:flex;\"><span>&lt;<span style=\"color:#f92672\">input<\/span> <span style=\"color:#a6e22e\">class<\/span><span style=\"color:#f92672\">=<\/span><span style=\"color:#e6db74\">&#34;form-control&#34;<\/span> <span style=\"color:#a6e22e\">id<\/span><span style=\"color:#f92672\">=<\/span><span style=\"color:#e6db74\">&#34;label&#34;<\/span> <span style=\"color:#960050;background-color:#1e0010\">[(<\/span><span style=\"color:#a6e22e\">ngModel<\/span><span style=\"color:#960050;background-color:#1e0010\">)]=&#39;<\/span><span style=\"color:#a6e22e\">modelValue<\/span><span style=\"color:#960050;background-color:#1e0010\">&#39;<\/span> <span style=\"color:#a6e22e\">required<\/span> <span style=\"color:#a6e22e\">myDirective<\/span>&gt;\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">Model<\/span><span style=\"color:#f92672\">:<\/span> {{ <span style=\"color:#a6e22e\">modelValue<\/span> }}\n<\/span><\/span><\/code><\/pre><\/div><p>In this snippet we&rsquo;re using the well known <em>banana in a box<\/em> syntax, which is the same as: <code>[ngModel]='modelValue' (ngModelChange)='modelValue = $event'<\/code>.<\/p>\n<p><a href=\"https:\/\/stackblitz.com\/edit\/ngmodelchange-error?file=src%2Fapp%2Fapp.component.html\" target=\"_blank\" rel=\"noopener\"><em>Here&rsquo;s the corresponding StackBlitz<\/em><\/a>.<\/p>\n<p>As soon as we start typing into the input, the problem becomes evident.<\/p>\n<h1 id=\"understanding-the-problem\">\n  <span>\n  Understanding the problem\n  <\/span>\n  <a href=\"#understanding-the-problem\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h1><blockquote>\n<p><code>ControlValueAccessor<\/code> does not refer to a certain entity (such as an <code>interface<\/code>), but to the concept behind it.<\/p>\n<\/blockquote>\n<p>Angular has <em>default value accessors<\/em> for certain elements, such as for <code>input type='text'<\/code>, <code>input type='checkbox'<\/code> etc&hellip;<\/p>\n<p>A <code>ControlValueAccessor<\/code> is the <em>middleman<\/em> between the VIEW layer and the MODEL layer. When a user types into an input, the VIEW notifies the <code>ControlValueAccessor<\/code>, which has the job to inform the MODEL.<\/p>\n<p><p class=\"markdown-image\">\n  <img src=\"images\/view.png\" alt=\"Content image\"  \/>\n<\/p><\/p>\n<p>For instance, when the <code>input<\/code> event occurs, the <code>onChange<\/code> method of the <code>ControlValueAccessor<\/code> will be called. <a href=\"https:\/\/github.com\/angular\/angular\/blob\/master\/packages\/forms\/src\/directives\/shared.ts#L93-L101\" target=\"_blank\" rel=\"noopener\">Here&rsquo;s how<\/a> <code>onChange<\/code> looks like <strong>for every<\/strong> <code>ControlValueAccessor<\/code>:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">function<\/span> <span style=\"color:#a6e22e\">setUpViewChangePipeline<\/span>(<span style=\"color:#a6e22e\">control<\/span>: <span style=\"color:#66d9ef\">FormControl<\/span>, <span style=\"color:#a6e22e\">dir<\/span>: <span style=\"color:#66d9ef\">NgControl<\/span>)<span style=\"color:#f92672\">:<\/span> <span style=\"color:#66d9ef\">void<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">dir<\/span>.<span style=\"color:#a6e22e\">valueAccessor<\/span><span style=\"color:#f92672\">!<\/span>.<span style=\"color:#a6e22e\">registerOnChange<\/span>((<span style=\"color:#a6e22e\">newValue<\/span>: <span style=\"color:#66d9ef\">any<\/span>) <span style=\"color:#f92672\">=&gt;<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">control<\/span>.<span style=\"color:#a6e22e\">_pendingValue<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">newValue<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">control<\/span>.<span style=\"color:#a6e22e\">_pendingChange<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">true<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">control<\/span>.<span style=\"color:#a6e22e\">_pendingDirty<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">true<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#a6e22e\">control<\/span>.<span style=\"color:#a6e22e\">updateOn<\/span> <span style=\"color:#f92672\">===<\/span> <span style=\"color:#e6db74\">&#39;change&#39;<\/span>) <span style=\"color:#a6e22e\">updateControl<\/span>(<span style=\"color:#a6e22e\">control<\/span>, <span style=\"color:#a6e22e\">dir<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>  });\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p>The magic happens in <a href=\"https:\/\/github.com\/angular\/angular\/blob\/master\/packages\/forms\/src\/directives\/shared.ts#L112-L117\" target=\"_blank\" rel=\"noopener\"><code>updateControl<\/code><\/a>:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">function<\/span> <span style=\"color:#a6e22e\">updateControl<\/span>(<span style=\"color:#a6e22e\">control<\/span>: <span style=\"color:#66d9ef\">FormControl<\/span>, <span style=\"color:#a6e22e\">dir<\/span>: <span style=\"color:#66d9ef\">NgControl<\/span>)<span style=\"color:#f92672\">:<\/span> <span style=\"color:#66d9ef\">void<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#a6e22e\">control<\/span>.<span style=\"color:#a6e22e\">_pendingDirty<\/span>) <span style=\"color:#a6e22e\">control<\/span>.<span style=\"color:#a6e22e\">markAsDirty<\/span>();\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">control<\/span>.<span style=\"color:#a6e22e\">setValue<\/span>(<span style=\"color:#a6e22e\">control<\/span>.<span style=\"color:#a6e22e\">_pendingValue<\/span>, {<span style=\"color:#a6e22e\">emitModelToViewChange<\/span>: <span style=\"color:#66d9ef\">false<\/span>});\n<\/span><\/span><span style=\"display:flex;\"><span> \n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#75715e\">\/\/ !\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>  <span style=\"color:#a6e22e\">dir<\/span>.<span style=\"color:#a6e22e\">viewToModelUpdate<\/span>(<span style=\"color:#a6e22e\">control<\/span>.<span style=\"color:#a6e22e\">_pendingValue<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">control<\/span>.<span style=\"color:#a6e22e\">_pendingChange<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">false<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p><a href=\"https:\/\/github.com\/angular\/angular\/blob\/master\/packages\/forms\/src\/directives\/ng_model.ts#L276-L279\" target=\"_blank\" rel=\"noopener\"><code>dir.viewToModelUpdate(control._pendingValue)<\/code><\/a> is what invokes the <code>ngModelChange<\/code> event in the custom directive.<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/* ... *\/<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">@Output<\/span>(<span style=\"color:#e6db74\">&#39;ngModelChange&#39;<\/span>) <span style=\"color:#a6e22e\">update<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">new<\/span> <span style=\"color:#a6e22e\">EventEmitter<\/span>();\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/* ... *\/<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">viewToModelUpdate<\/span>(<span style=\"color:#a6e22e\">newValue<\/span>: <span style=\"color:#66d9ef\">any<\/span>)<span style=\"color:#f92672\">:<\/span> <span style=\"color:#66d9ef\">void<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">viewModel<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">newValue<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">update<\/span>.<span style=\"color:#a6e22e\">emit<\/span>(<span style=\"color:#a6e22e\">newValue<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/* ... *\/<\/span>\n<\/span><\/span><\/code><\/pre><\/div><p>What this means is that the <strong>model value<\/strong> is the value from the input (in lowercase). Because <code>ControlValueAccessor.writeValue<\/code> <strong>only<\/strong> writes the value to the VIEW, there will be a <em>delay<\/em> between the VIEW&rsquo;s value and the MODEL&rsquo;s value. Here is how <a href=\"https:\/\/github.com\/angular\/angular\/blob\/master\/packages\/forms\/src\/directives\/default_value_accessor.ts#L104-L107\" target=\"_blank\" rel=\"noopener\"><code>DefaultValueAccessor.writeValue()<\/code><\/a> is defined:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">writeValue<\/span>(<span style=\"color:#a6e22e\">value<\/span>: <span style=\"color:#66d9ef\">any<\/span>)<span style=\"color:#f92672\">:<\/span> <span style=\"color:#66d9ef\">void<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">normalizedValue<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">value<\/span> <span style=\"color:#f92672\">==<\/span> <span style=\"color:#66d9ef\">null<\/span> <span style=\"color:#f92672\">?<\/span> <span style=\"color:#e6db74\">&#39;&#39;<\/span> <span style=\"color:#f92672\">:<\/span> <span style=\"color:#a6e22e\">value<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">_renderer<\/span>.<span style=\"color:#a6e22e\">setProperty<\/span>(<span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">_elementRef<\/span>.<span style=\"color:#a6e22e\">nativeElement<\/span>, <span style=\"color:#e6db74\">&#39;value&#39;<\/span>, <span style=\"color:#a6e22e\">normalizedValue<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p>It&rsquo;s worth mentioning that <code>FormControl.setValue(val)<\/code> will write <code>val<\/code> to <strong>both<\/strong> layers, VIEW and MODEL, but if we were to use this, there would be an <strong>infinite loop<\/strong>, since <code>setValue()<\/code> internally calls <code>viewToModelUpdate<\/code>(because the MODEL has to be updated, e.g the <code>modelValue<\/code> in <code>[(ngModel)]='modelValue'<\/code>), and <code>viewToModelUpdate<\/code> calls <code>setValue()<\/code>.<\/p>\n<p><p class=\"markdown-image\">\n  <img src=\"images\/setvalue.png\" alt=\"Content image\"  \/>\n<\/p><\/p>\n<p>And <a href=\"https:\/\/github.com\/angular\/angular\/blob\/master\/packages\/forms\/src\/directives\/shared.ts#L119-L127\" target=\"_blank\" rel=\"noopener\">this<\/a> is the snippet depicted in the image above:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">function<\/span> <span style=\"color:#a6e22e\">setUpModelChangePipeline<\/span>(<span style=\"color:#a6e22e\">control<\/span>: <span style=\"color:#66d9ef\">FormControl<\/span>, <span style=\"color:#a6e22e\">dir<\/span>: <span style=\"color:#66d9ef\">NgControl<\/span>)<span style=\"color:#f92672\">:<\/span> <span style=\"color:#66d9ef\">void<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">control<\/span>.<span style=\"color:#a6e22e\">registerOnChange<\/span>((<span style=\"color:#a6e22e\">newValue<\/span>: <span style=\"color:#66d9ef\">any<\/span>, <span style=\"color:#a6e22e\">emitModelEvent<\/span>: <span style=\"color:#66d9ef\">boolean<\/span>) <span style=\"color:#f92672\">=&gt;<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#75715e\">\/\/ control -&gt; view\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>    <span style=\"color:#a6e22e\">dir<\/span>.<span style=\"color:#a6e22e\">valueAccessor<\/span><span style=\"color:#f92672\">!<\/span>.<span style=\"color:#a6e22e\">writeValue<\/span>(<span style=\"color:#a6e22e\">newValue<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#75715e\">\/\/ control -&gt; ngModel\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>    <span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#a6e22e\">emitModelEvent<\/span>) <span style=\"color:#a6e22e\">dir<\/span>.<span style=\"color:#a6e22e\">viewToModelUpdate<\/span>(<span style=\"color:#a6e22e\">newValue<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>  });\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><h2 id=\"the-solution\">\n  <span>\n  The solution\n  <\/span>\n  <a href=\"#the-solution\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><p>A way to solve the problem is to add this snippet to the directive:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">ngOnInit<\/span> () {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">initialOnChange<\/span> <span style=\"color:#f92672\">=<\/span> (<span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">ngControl<\/span>.<span style=\"color:#a6e22e\">valueAccessor<\/span> <span style=\"color:#66d9ef\">as<\/span> <span style=\"color:#66d9ef\">any<\/span>).<span style=\"color:#a6e22e\">onChange<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>  (<span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">ngControl<\/span>.<span style=\"color:#a6e22e\">valueAccessor<\/span> <span style=\"color:#66d9ef\">as<\/span> <span style=\"color:#66d9ef\">any<\/span>).<span style=\"color:#a6e22e\">onChange<\/span> <span style=\"color:#f92672\">=<\/span> (<span style=\"color:#a6e22e\">value<\/span>) <span style=\"color:#f92672\">=&gt;<\/span> <span style=\"color:#a6e22e\">initialOnChange<\/span>(<span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">processInput<\/span>(<span style=\"color:#a6e22e\">value<\/span>));\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p>With this approach, we&rsquo;re modifying the data at the VIEW layer, before it is sent to the <code>ControlValueAccessor<\/code>.<\/p>\n<p>And we can be sure that <code>onChange<\/code> exists on every built-in <code>ControlValueAccessor<\/code>:<\/p>\n<p><p class=\"markdown-image\">\n  <img src=\"images\/Screenshot-from-2020-08-31-15-22-03.png\" alt=\"Content image\"  \/>\n<\/p><\/p>\n<p>If you are going to create a custom one, just make sure it has an <code>onChange<\/code> property. TypeScript can help you with that.<\/p>\n<p><a href=\"https:\/\/stackblitz.com\/edit\/angular-ivy-kv3g3f?file=src%2Fapp%2Fapp.component.html\" target=\"_blank\" rel=\"noopener\"><em>StackBlitz<\/em><\/a>.<\/p>\n<h2 id=\"conclusion\">\n  <span>\n  Conclusion\n  <\/span>\n  <a href=\"#conclusion\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><p>A <code>ControlValueAccessor<\/code> is responsible for keeping in sync the 2 main layers, VIEW and MODEL. By understanding some of the inner workings of Angular Forms, we were able to see why the problem occurred and how to solve it.<\/p>\n<p>Thanks for reading!<\/p>\n"},{"title":"Understanding the magic behind @ngrx\/effects","link":"https:\/\/andreigatej.dev\/blog\/ngrx-effectsmodule\/","pubDate":"Mon, 20 Apr 2020 00:00:00 +0000","guid":"https:\/\/andreigatej.dev\/blog\/ngrx-effectsmodule\/","description":"<p><em>This article has been published on <a href=\"https:\/\/indepth.dev\/posts\/1206\/understanding-the-magic-behind-ngrx-effects\" target=\"_blank\" rel=\"noopener\">indepth.dev<\/a>.<\/em><\/p>\n<h2 id=\"introduction\">\n  <span>\n  Introduction\n  <\/span>\n  <a href=\"#introduction\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><p>NgRx&rsquo;s underlying mechanisms are something definitely worth exploring. By the end of this article you&rsquo;ll hopefully understand not only how <code>ngrx\/effects<\/code> package works under the hood, but also how <code>ngrx\/store<\/code> and <code>ngrx\/effects<\/code> work together.<\/p>\n<p>One of the most fascinating discoveries was the way actions are handled in this whole process. As you may know, an action is a constituent of a reducer, as well as of an effect. <strong>NgRx ensures that actions are first handled by the reducers, after which they will eventually be intercepted by the effects.<\/strong> We&rsquo;ll make other interesting discoveries in this article. Let&rsquo;s dive in.<\/p>\n<h2 id=\"providing-the-effects\">\n  <span>\n  Providing the effects\n  <\/span>\n  <a href=\"#providing-the-effects\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><p>For this purpose, we can use <code>EffectsModule.forRoot([effectClass])<\/code>, <code>EffectsModule.forFeature([effectClass])<\/code> or the <code>USER_PROVIDED_EFFECTS<\/code> <strong>multi token<\/strong>. The <code>forRoot<\/code> method should be used <strong>only once<\/strong> as it will instantiate other essential services such as <code>EffectsRunner<\/code> or <code>EffectSources<\/code>.<\/p>\n<blockquote>\n<p>If you use the token approach, you <strong>must<\/strong> also use either <code>forRoot<\/code> or <code>forFeature<\/code>, because providing only the token won&rsquo;t be enough as it depends on <code>EffectsRootModule<\/code> or <code>EffectsFeatureModule<\/code>.<\/p>\n<\/blockquote>\n<p>Once the effects (classes) are registered, in order to set them up, an observable will be created (with the help of <code>EffectSources<\/code>) and subscribed to (thanks to <code>EffectRunner<\/code>); we&rsquo;ll explore it in the next section.<\/p>\n<p>The observable&rsquo;s emitted values will be the <strong>instances<\/strong> of those registered classes:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ EffectsModule.forRoot(rootEffects)\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>{\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">return<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">ngModule<\/span>: <span style=\"color:#66d9ef\">EffectsRootModule<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">providers<\/span><span style=\"color:#f92672\">:<\/span> [\n<\/span><\/span><span style=\"display:flex;\"><span>      {\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#75715e\">\/\/ Make sure the `forRoot` static method is called only once\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>        <span style=\"color:#a6e22e\">provide<\/span>: <span style=\"color:#66d9ef\">_ROOT_EFFECTS_GUARD<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#a6e22e\">useFactory<\/span>: <span style=\"color:#66d9ef\">_provideForRootGuard<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#a6e22e\">deps<\/span><span style=\"color:#f92672\">:<\/span> [[<span style=\"color:#a6e22e\">EffectsRunner<\/span>, <span style=\"color:#66d9ef\">new<\/span> <span style=\"color:#a6e22e\">Optional<\/span>(), <span style=\"color:#66d9ef\">new<\/span> <span style=\"color:#a6e22e\">SkipSelf<\/span>()]],\n<\/span><\/span><span style=\"display:flex;\"><span>      },\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#a6e22e\">EffectsRunner<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#a6e22e\">EffectSources<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#a6e22e\">Actions<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#a6e22e\">rootEffects<\/span>, <span style=\"color:#75715e\">\/\/ The array of classes(effects)\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>      {\n<\/span><\/span><span style=\"display:flex;\"><span>          <span style=\"color:#75715e\">\/\/ Dependency for `ROOT_EFFECTS`\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>          <span style=\"color:#a6e22e\">provide<\/span>: <span style=\"color:#66d9ef\">_ROOT_EFFECTS<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>          <span style=\"color:#75715e\">\/\/ Providing it as an array because of how `createEffects` is implemented\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>          <span style=\"color:#a6e22e\">useValue<\/span><span style=\"color:#f92672\">:<\/span> [<span style=\"color:#a6e22e\">rootEffects<\/span>],\n<\/span><\/span><span style=\"display:flex;\"><span>        },\n<\/span><\/span><span style=\"display:flex;\"><span>        {\n<\/span><\/span><span style=\"display:flex;\"><span>          <span style=\"color:#75715e\">\/\/ This token would be provided by the user in its separate module\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>          <span style=\"color:#a6e22e\">provide<\/span>: <span style=\"color:#66d9ef\">USER_PROVIDED_EFFECTS<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>          <span style=\"color:#a6e22e\">multi<\/span>: <span style=\"color:#66d9ef\">true<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>          <span style=\"color:#a6e22e\">useValue<\/span><span style=\"color:#f92672\">:<\/span> [], <span style=\"color:#75715e\">\/\/ [UserProvidedEffectsClass]\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>        },\n<\/span><\/span><span style=\"display:flex;\"><span>        {\n<\/span><\/span><span style=\"display:flex;\"><span>          <span style=\"color:#a6e22e\">provide<\/span>: <span style=\"color:#66d9ef\">ROOT_EFFECTS<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>          <span style=\"color:#a6e22e\">useFactory<\/span>: <span style=\"color:#66d9ef\">createEffects<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>          <span style=\"color:#a6e22e\">deps<\/span><span style=\"color:#f92672\">:<\/span> [<span style=\"color:#a6e22e\">Injector<\/span>, <span style=\"color:#a6e22e\">_ROOT_EFFECTS<\/span>, <span style=\"color:#a6e22e\">USER_PROVIDED_EFFECTS<\/span>],\n<\/span><\/span><span style=\"display:flex;\"><span>        },\n<\/span><\/span><span style=\"display:flex;\"><span>    ],\n<\/span><\/span><span style=\"display:flex;\"><span>  };\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">export<\/span> <span style=\"color:#66d9ef\">function<\/span> <span style=\"color:#a6e22e\">createEffects<\/span>(\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">injector<\/span>: <span style=\"color:#66d9ef\">Injector<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">effectGroups<\/span>: <span style=\"color:#66d9ef\">Type<\/span>&lt;<span style=\"color:#f92672\">any<\/span>&gt;[][],\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">userProvidedEffectGroups<\/span>: <span style=\"color:#66d9ef\">Type<\/span>&lt;<span style=\"color:#f92672\">any<\/span>&gt;[][]\n<\/span><\/span><span style=\"display:flex;\"><span>)<span style=\"color:#f92672\">:<\/span> <span style=\"color:#66d9ef\">any<\/span>[] {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">mergedEffects<\/span>: <span style=\"color:#66d9ef\">Type<\/span>&lt;<span style=\"color:#f92672\">any<\/span>&gt;[] <span style=\"color:#f92672\">=<\/span> [];\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">for<\/span> (<span style=\"color:#66d9ef\">let<\/span> <span style=\"color:#a6e22e\">effectGroup<\/span> <span style=\"color:#66d9ef\">of<\/span> <span style=\"color:#a6e22e\">effectGroups<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">mergedEffects<\/span>.<span style=\"color:#a6e22e\">push<\/span>(...<span style=\"color:#a6e22e\">effectGroup<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>  }\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">for<\/span> (<span style=\"color:#66d9ef\">let<\/span> <span style=\"color:#a6e22e\">userProvidedEffectGroup<\/span> <span style=\"color:#66d9ef\">of<\/span> <span style=\"color:#a6e22e\">userProvidedEffectGroups<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">mergedEffects<\/span>.<span style=\"color:#a6e22e\">push<\/span>(...<span style=\"color:#a6e22e\">userProvidedEffectGroup<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>  }\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#a6e22e\">createEffectInstances<\/span>(<span style=\"color:#a6e22e\">injector<\/span>, <span style=\"color:#a6e22e\">mergedEffects<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ Here the instances are created\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span><span style=\"color:#66d9ef\">export<\/span> <span style=\"color:#66d9ef\">function<\/span> <span style=\"color:#a6e22e\">createEffectInstances<\/span>(<span style=\"color:#75715e\">\/* ... *\/<\/span>)<span style=\"color:#f92672\">:<\/span> <span style=\"color:#66d9ef\">any<\/span>[] {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#a6e22e\">effects<\/span>.<span style=\"color:#a6e22e\">map<\/span>(<span style=\"color:#a6e22e\">effect<\/span> <span style=\"color:#f92672\">=&gt;<\/span> <span style=\"color:#a6e22e\">injector<\/span>.<span style=\"color:#66d9ef\">get<\/span>(<span style=\"color:#a6e22e\">effect<\/span>));\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p>In this case, <code>EffectsRootModule<\/code> will inject <code>ROOT_EFFECTS<\/code> which will contain the needed instances and will push them into the <em>effects stream<\/em>:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">@NgModule<\/span>({})\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">export<\/span> <span style=\"color:#66d9ef\">class<\/span> <span style=\"color:#a6e22e\">EffectsRootModule<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">constructor<\/span>(\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">private<\/span> <span style=\"color:#a6e22e\">sources<\/span>: <span style=\"color:#66d9ef\">EffectSources<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">runner<\/span>: <span style=\"color:#66d9ef\">EffectsRunner<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">store<\/span>: <span style=\"color:#66d9ef\">Store<\/span>&lt;<span style=\"color:#f92672\">any<\/span>&gt;,\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">@Inject<\/span>(<span style=\"color:#a6e22e\">ROOT_EFFECTS<\/span>) <span style=\"color:#a6e22e\">rootEffects<\/span>: <span style=\"color:#66d9ef\">any<\/span>[],\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#75715e\">\/* ... *\/<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>  ) {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#75715e\">\/\/ Subscribe to the `effects stream`\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>    <span style=\"color:#75715e\">\/\/ The `observer` is the Store entity \n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>    <span style=\"color:#a6e22e\">runner<\/span>.<span style=\"color:#a6e22e\">start<\/span>();\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">rootEffects<\/span>.<span style=\"color:#a6e22e\">forEach<\/span>(<span style=\"color:#a6e22e\">effectSourceInstance<\/span> <span style=\"color:#f92672\">=&gt;<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#75715e\">\/\/ Push values into the stream\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>      <span style=\"color:#a6e22e\">sources<\/span>.<span style=\"color:#a6e22e\">addEffects<\/span>(<span style=\"color:#a6e22e\">effectSourceInstance<\/span>)\n<\/span><\/span><span style=\"display:flex;\"><span>    );\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">store<\/span>.<span style=\"color:#a6e22e\">dispatch<\/span>({ <span style=\"color:#66d9ef\">type<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#a6e22e\">ROOT_EFFECTS_INIT<\/span> });\n<\/span><\/span><span style=\"display:flex;\"><span>  }\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">addEffects<\/span>(<span style=\"color:#a6e22e\">effectSourceInstance<\/span>: <span style=\"color:#66d9ef\">any<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">sources<\/span>.<span style=\"color:#a6e22e\">addEffects<\/span>(<span style=\"color:#a6e22e\">effectSourceInstance<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>  }\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p>As a side note, you can perform specific state changes when the root effects are initialized by registering the <code>rootEffectsInit<\/code> action in a reducer:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">createReducer<\/span>(\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">initialState<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">on<\/span>(<span style=\"color:#a6e22e\">rootEffectsInit<\/span>, (<span style=\"color:#a6e22e\">s<\/span>, <span style=\"color:#a6e22e\">a<\/span>) <span style=\"color:#f92672\">=<\/span> {<span style=\"color:#75715e\">\/* ... *\/<\/span>})\n<\/span><\/span><span style=\"display:flex;\"><span>)\n<\/span><\/span><\/code><\/pre><\/div><p>The <code>EffectsFeatureModule<\/code> (returned from <code>EffectsModule.forFeature()<\/code>) follows a similar approach, except that it will only push the effects instances into the stream:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">@NgModule<\/span>({})\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">export<\/span> <span style=\"color:#66d9ef\">class<\/span> <span style=\"color:#a6e22e\">EffectsFeatureModule<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">constructor<\/span>(\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#75715e\">\/\/ Make sure the essential services(EffectsRunner, EffectSources)\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>    <span style=\"color:#75715e\">\/\/ are initialized first\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>    <span style=\"color:#a6e22e\">root<\/span>: <span style=\"color:#66d9ef\">EffectsRootModule<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">@Inject<\/span>(<span style=\"color:#a6e22e\">FEATURE_EFFECTS<\/span>) <span style=\"color:#a6e22e\">effectSourceGroups<\/span>: <span style=\"color:#66d9ef\">any<\/span>[][],\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#75715e\">\/* ... *\/<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>  ) {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">effectSourceGroups<\/span>.<span style=\"color:#a6e22e\">forEach<\/span>(<span style=\"color:#a6e22e\">group<\/span> <span style=\"color:#f92672\">=&gt;<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#a6e22e\">group<\/span>.<span style=\"color:#a6e22e\">forEach<\/span>(<span style=\"color:#a6e22e\">effectSourceInstance<\/span> <span style=\"color:#f92672\">=&gt;<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#a6e22e\">root<\/span>.<span style=\"color:#a6e22e\">addEffects<\/span>(<span style=\"color:#a6e22e\">effectSourceInstance<\/span>)\n<\/span><\/span><span style=\"display:flex;\"><span>      )\n<\/span><\/span><span style=\"display:flex;\"><span>    );\n<\/span><\/span><span style=\"display:flex;\"><span>  }\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p>There is also another small difference. The <code>FEATURE_EFFECTS<\/code> is a <code>multi<\/code> provider token, which means that, when injected, it will contain an array of all provided classes.<\/p>\n<h2 id=\"the-effects-stream\">\n  <span>\n  The effects stream\n  <\/span>\n  <a href=\"#the-effects-stream\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><p>As described in the previous section, the <code>EffectsRootModule<\/code> does a bit more than just instantiating the effects classes. It is also in charge of creating a <strong>single stream<\/strong> from all the effects (e.g: results of <code>createEffect<\/code>) of the newly created instances and subscribing to it.<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">@NgModule<\/span>({})\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">export<\/span> <span style=\"color:#66d9ef\">class<\/span> <span style=\"color:#a6e22e\">EffectsRootModule<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">constructor<\/span>(\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">private<\/span> <span style=\"color:#a6e22e\">sources<\/span>: <span style=\"color:#66d9ef\">EffectSources<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">runner<\/span>: <span style=\"color:#66d9ef\">EffectsRunner<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">store<\/span>: <span style=\"color:#66d9ef\">Store<\/span>&lt;<span style=\"color:#f92672\">any<\/span>&gt;,\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">@Inject<\/span>(<span style=\"color:#a6e22e\">ROOT_EFFECTS<\/span>) <span style=\"color:#a6e22e\">rootEffects<\/span>: <span style=\"color:#66d9ef\">any<\/span>[],\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">@Optional<\/span>() <span style=\"color:#a6e22e\">storeRootModule<\/span>: <span style=\"color:#66d9ef\">StoreRootModule<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">@Optional<\/span>() <span style=\"color:#a6e22e\">storeFeatureModule<\/span>: <span style=\"color:#66d9ef\">StoreFeatureModule<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">@Optional<\/span>()\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">@Inject<\/span>(<span style=\"color:#a6e22e\">_ROOT_EFFECTS_GUARD<\/span>)\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">guard<\/span>: <span style=\"color:#66d9ef\">any<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>  ) {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">runner<\/span>.<span style=\"color:#a6e22e\">start<\/span>(); <span style=\"color:#75715e\">\/\/ Creating the stream\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">rootEffects<\/span>.<span style=\"color:#a6e22e\">forEach<\/span>(<span style=\"color:#a6e22e\">effectSourceInstance<\/span> <span style=\"color:#f92672\">=&gt;<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#a6e22e\">sources<\/span>.<span style=\"color:#a6e22e\">addEffects<\/span>(<span style=\"color:#a6e22e\">effectSourceInstance<\/span>)\n<\/span><\/span><span style=\"display:flex;\"><span>    );\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">store<\/span>.<span style=\"color:#a6e22e\">dispatch<\/span>({ <span style=\"color:#66d9ef\">type<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#a6e22e\">ROOT_EFFECTS_INIT<\/span> });\n<\/span><\/span><span style=\"display:flex;\"><span>  }\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">addEffects<\/span>(<span style=\"color:#a6e22e\">effectSourceInstance<\/span>: <span style=\"color:#66d9ef\">any<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#75715e\">\/\/ Pushing values into the stream\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>    <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">sources<\/span>.<span style=\"color:#a6e22e\">addEffects<\/span>(<span style=\"color:#a6e22e\">effectSourceInstance<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>  }\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p><code>@Optional() storeRootModule: StoreRootModule<\/code> and <code>@Optional() storeFeatureModule: StoreFeatureModule<\/code> will make sure that effects are initialized <strong>after<\/strong> the <code>ngrx\/store<\/code> entities (the results of <code>StoreModule.forRoot()<\/code> and eventually <code>StoreModule.forFeature()<\/code>) have been initialized. This <em>beforehand<\/em> initialization includes:<\/p>\n<ul>\n<li>the creation of the <strong>reducers object<\/strong>: all the registered reducers, those from <strong>feature modules<\/strong> as well, will be merged into one big object that will represent the shape of the app<\/li>\n<li>the <code>State<\/code> entity - where the app information is kept, also where the place actions <em>meet<\/em> reducers, meaning it&rsquo;s where reducers being invoked, which may cause state changes<\/li>\n<li>the <code>Store<\/code> entity - the <em>middleman<\/em> between the data consumer(e.g: a smart component) and the model(the <code>State<\/code> entity)<\/li>\n<li>the <code>ScannedActionsSubject<\/code> - the <strong>stream<\/strong> that the <strong>effects (indirectly) subscribe<\/strong> to; more on this in <strong><a href=\"#the-actions-stream\"><em>The <code>actions<\/code> stream<\/em><\/a>.<\/strong><\/li>\n<\/ul>\n<p><code>runner.start()<\/code> will create a <strong>subscription<\/strong> to a <strong>stream<\/strong> resulted from the <strong>merging<\/strong> of all <strong>registered effects<\/strong> (more on this in the upcoming section). In other words, all the effects(e.g: those created by <code>createEffect<\/code> for example) will be merged into one <strong>single observable<\/strong> whose <strong>emitted<\/strong> values will be <strong>actions<\/strong>.<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ EffectsRunner\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">start() {<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#f92672\">!<\/span><span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">effectsSubscription<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">effectsSubscription<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">effectSources<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>      .<span style=\"color:#a6e22e\">toActions<\/span>()\n<\/span><\/span><span style=\"display:flex;\"><span>      .<span style=\"color:#a6e22e\">subscribe<\/span>(<span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">store<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>  }\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p>The stream&rsquo;s observer will be the <code>Store<\/code> entity. This is possible because it implements the <code>Observer<\/code> interface:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">export<\/span> <span style=\"color:#66d9ef\">class<\/span> <span style=\"color:#a6e22e\">Store<\/span>&lt;<span style=\"color:#f92672\">T<\/span> <span style=\"color:#960050;background-color:#1e0010\">=<\/span> <span style=\"color:#a6e22e\">object<\/span>&gt; <span style=\"color:#66d9ef\">extends<\/span> <span style=\"color:#a6e22e\">Observable<\/span>&lt;<span style=\"color:#f92672\">T<\/span>&gt;\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">implements<\/span> <span style=\"color:#a6e22e\">Observer<\/span>&lt;<span style=\"color:#f92672\">Action<\/span>&gt; {\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">next<\/span>(<span style=\"color:#a6e22e\">action<\/span>: <span style=\"color:#66d9ef\">Action<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">actionsObserver<\/span>.<span style=\"color:#a6e22e\">next<\/span>(<span style=\"color:#a6e22e\">action<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>    }\n<\/span><\/span><span style=\"display:flex;\"><span>  }\n<\/span><\/span><\/code><\/pre><\/div><p>meaning that any <strong>action resulted<\/strong> from the <strong>effects<\/strong> will be intercepted by the <code>Store<\/code> which will in turn propagate it further so state changes can occur.<\/p>\n<h2 id=\"effectsources\">\n  <span>\n  EffectSources\n  <\/span>\n  <a href=\"#effectsources\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><p>It is the place where all the <strong>registered effects<\/strong> will be <strong>merged<\/strong> into <strong>one observable,<\/strong> whose emitted values (<strong>actions<\/strong>) will be intercepted by the <code>Store<\/code> entity, which is responsible for dispatching them, so that the app state can be updated. It is also the entity that what allows <strong>lifecycle hooks<\/strong> to be called.<\/p>\n<p>The <em>merging behavior<\/em> can be achieved with <code>EffectSources.toActions()<\/code> from below:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">export<\/span> <span style=\"color:#66d9ef\">class<\/span> <span style=\"color:#a6e22e\">EffectSources<\/span> <span style=\"color:#66d9ef\">extends<\/span> <span style=\"color:#a6e22e\">Subject<\/span>&lt;<span style=\"color:#f92672\">any<\/span>&gt; {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">constructor<\/span>(\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#75715e\">\/* ... *\/<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">private<\/span> <span style=\"color:#a6e22e\">store<\/span>: <span style=\"color:#66d9ef\">Store<\/span>&lt;<span style=\"color:#f92672\">any<\/span>&gt;,\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#75715e\">\/* ... *\/<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>  ) {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">super<\/span>();\n<\/span><\/span><span style=\"display:flex;\"><span>  }\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#75715e\">\/\/ Pushing an effect into the stream created by `toActions()`\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>  <span style=\"color:#a6e22e\">addEffects<\/span>(<span style=\"color:#a6e22e\">effectSourceInstance<\/span>: <span style=\"color:#66d9ef\">any<\/span>)<span style=\"color:#f92672\">:<\/span> <span style=\"color:#66d9ef\">void<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">next<\/span>(<span style=\"color:#a6e22e\">effectSourceInstance<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>  }\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">toActions<\/span>()<span style=\"color:#f92672\">:<\/span> <span style=\"color:#a6e22e\">Observable<\/span>&lt;<span style=\"color:#f92672\">Action<\/span>&gt; {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">pipe<\/span>(\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#a6e22e\">groupBy<\/span>(<span style=\"color:#a6e22e\">getSourceForInstance<\/span>),\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#a6e22e\">mergeMap<\/span>(<span style=\"color:#a6e22e\">source$<\/span> <span style=\"color:#f92672\">=&gt;<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#a6e22e\">source$<\/span>.<span style=\"color:#a6e22e\">pipe<\/span>(<span style=\"color:#a6e22e\">groupBy<\/span>(<span style=\"color:#a6e22e\">effectsInstance<\/span>));\n<\/span><\/span><span style=\"display:flex;\"><span>      }),\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#a6e22e\">mergeMap<\/span>(<span style=\"color:#a6e22e\">source$<\/span> <span style=\"color:#f92672\">=&gt;<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">effect$<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">source$<\/span>.<span style=\"color:#a6e22e\">pipe<\/span>(\n<\/span><\/span><span style=\"display:flex;\"><span>          <span style=\"color:#a6e22e\">exhaustMap<\/span>(<span style=\"color:#a6e22e\">sourceInstance<\/span> <span style=\"color:#f92672\">=&gt;<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>            <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#a6e22e\">resolveEffectSource<\/span>(\n<\/span><\/span><span style=\"display:flex;\"><span>              <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">errorHandler<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>              <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">effectsErrorHandler<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>            )(<span style=\"color:#a6e22e\">sourceInstance<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>          }),\n<\/span><\/span><span style=\"display:flex;\"><span>          <span style=\"color:#a6e22e\">map<\/span>(<span style=\"color:#a6e22e\">output<\/span> <span style=\"color:#f92672\">=&gt;<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>            <span style=\"color:#a6e22e\">reportInvalidActions<\/span>(<span style=\"color:#a6e22e\">output<\/span>, <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">errorHandler<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>            <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#a6e22e\">output<\/span>.<span style=\"color:#a6e22e\">notification<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>          }),\n<\/span><\/span><span style=\"display:flex;\"><span>          <span style=\"color:#a6e22e\">filter<\/span>(\n<\/span><\/span><span style=\"display:flex;\"><span>            (<span style=\"color:#a6e22e\">notification<\/span>)<span style=\"color:#f92672\">:<\/span> <span style=\"color:#a6e22e\">notification<\/span> <span style=\"color:#66d9ef\">is<\/span> <span style=\"color:#a6e22e\">Notification<\/span>&lt;<span style=\"color:#f92672\">Action<\/span>&gt; <span style=\"color:#f92672\">=&gt;<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>              <span style=\"color:#a6e22e\">notification<\/span>.<span style=\"color:#a6e22e\">kind<\/span> <span style=\"color:#f92672\">===<\/span> <span style=\"color:#e6db74\">&#39;N&#39;<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>          ),\n<\/span><\/span><span style=\"display:flex;\"><span>          <span style=\"color:#a6e22e\">dematerialize<\/span>()\n<\/span><\/span><span style=\"display:flex;\"><span>        );\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#75715e\">\/\/ start the stream with an INIT action\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>        <span style=\"color:#75715e\">\/\/ do this only for the first Effect instance\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>        <span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">init$<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">source$<\/span>.<span style=\"color:#a6e22e\">pipe<\/span>(\n<\/span><\/span><span style=\"display:flex;\"><span>          <span style=\"color:#a6e22e\">take<\/span>(<span style=\"color:#ae81ff\">1<\/span>),\n<\/span><\/span><span style=\"display:flex;\"><span>          <span style=\"color:#a6e22e\">filter<\/span>(<span style=\"color:#a6e22e\">isOnInitEffects<\/span>),\n<\/span><\/span><span style=\"display:flex;\"><span>          <span style=\"color:#a6e22e\">map<\/span>(<span style=\"color:#a6e22e\">instance<\/span> <span style=\"color:#f92672\">=&gt;<\/span> <span style=\"color:#a6e22e\">instance<\/span>.<span style=\"color:#a6e22e\">ngrxOnInitEffects<\/span>())\n<\/span><\/span><span style=\"display:flex;\"><span>        );\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#a6e22e\">merge<\/span>(<span style=\"color:#a6e22e\">effect$<\/span>, <span style=\"color:#a6e22e\">init$<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>      })\n<\/span><\/span><span style=\"display:flex;\"><span>    );\n<\/span><\/span><span style=\"display:flex;\"><span>  }\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p>Let&rsquo;s understand what it actually does by going through each significant block:<\/p>\n<ul>\n<li>group the effects by their source(the instance&rsquo;s prototype, the class which created the instance)<br>\nAs you know, <code>groupBy<\/code> will return an <strong>observable<\/strong> for each <strong>new key<\/strong> found. Then, if a value whose key is not new arrives, <code>groupBy<\/code> will use an existing observable and will push this new value through it.<br>\nThis thing happens here(<code>groupBy(getSourceForInstance)<\/code>), the key is the class that created this current instance, meaning that if there are 3 <strong>distinct<\/strong> effect classes, <code>groupBy<\/code> will emit 3 observables.<\/li>\n<li>group the instances(the effects) by their identifiers<\/li>\n<\/ul>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">mergeMap<\/span>(<span style=\"color:#a6e22e\">source$<\/span> <span style=\"color:#f92672\">=&gt;<\/span> { <span style=\"color:#75715e\">\/\/ &lt;- `source$` an observable that is resulted from the previous `groupBy`\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>  <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#a6e22e\">source$<\/span>.<span style=\"color:#a6e22e\">pipe<\/span>(<span style=\"color:#a6e22e\">groupBy<\/span>(<span style=\"color:#a6e22e\">effectsInstance<\/span>));\n<\/span><\/span><span style=\"display:flex;\"><span>}),\n<\/span><\/span><\/code><\/pre><\/div><p><code>mergeMap<\/code> is used because the first <code>groupBy<\/code> may emit multiple observables and the expected behavior is to handle all of them. Now, if the same effect class is loaded multiple times, <strong>only one instance<\/strong> will be used because these classes, by default, have the same identifier(and there can be only <strong>one class per identifier<\/strong>):<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">function<\/span> <span style=\"color:#a6e22e\">effectsInstance<\/span>(<span style=\"color:#a6e22e\">sourceInstance<\/span>: <span style=\"color:#66d9ef\">any<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#a6e22e\">isOnIdentifyEffects<\/span>(<span style=\"color:#a6e22e\">sourceInstance<\/span>)) {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#a6e22e\">sourceInstance<\/span>.<span style=\"color:#a6e22e\">ngrxOnIdentifyEffects<\/span>();\n<\/span><\/span><span style=\"display:flex;\"><span>  }\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#e6db74\">&#39;&#39;<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p>With <code>ngrxOnIdentifyEffects<\/code>(required by the <code>OnIdentityEffects<\/code> interface), we can specify a unique identifier for the class that contains the effects.<\/p>\n<p>This, alongside <code>groupBy(effectsInstance)<\/code> and eventually <code>exhaustMap<\/code>, will make sure that only the first unique instance is used.<br>\nFor example, if we have <code>EffectsModule.forRoot([A, A, A])<\/code>and they have the same identifier(e.g: <code>''<\/code> by default), the second <code>groupBy<\/code> will emit only <strong>one observable<\/strong> with <strong>3 items<\/strong>.<\/p>\n<p>With the help of <code>exhaustMap<\/code><\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">mergeMap<\/span>(<span style=\"color:#a6e22e\">source$<\/span> <span style=\"color:#f92672\">=&gt;<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">effect$<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">source$<\/span>.<span style=\"color:#a6e22e\">pipe<\/span>(\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#a6e22e\">exhaustMap<\/span>(<span style=\"color:#a6e22e\">sourceInstance<\/span> <span style=\"color:#f92672\">=&gt;<\/span> { <span style=\"color:#75715e\">\/* ... *\/<\/span> }),\n<\/span><\/span><span style=\"display:flex;\"><span>    )\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#75715e\">\/* ... *\/<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>  }\n<\/span><\/span><span style=\"display:flex;\"><span>)\n<\/span><\/span><\/code><\/pre><\/div><p>only one item out of 3 (the first <code>A<\/code> in this case) will be taken into account.<\/p>\n<p>Internally, <code>exhaustMap<\/code> uses a flag (<code>hasSubscription<\/code>) to check whether there is an active inner subscription going on or not. You can inspect the relevant code <a href=\"https:\/\/github.com\/ReactiveX\/rxjs\/blob\/master\/src\/internal\/operators\/exhaustMap.ts#L105-L122\" target=\"_blank\" rel=\"noopener\">here<\/a>.<\/p>\n<ul>\n<li>merge all the effects into a single stream<\/li>\n<\/ul>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ `mergeMap` - for each emitted observable(emitted by the second `groupBy`)\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ perform the same logic: merge all the effects(class properties)\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ into one single observable\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span><span style=\"color:#a6e22e\">mergeMap<\/span>(<span style=\"color:#a6e22e\">source$<\/span> <span style=\"color:#f92672\">=&gt;<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">effect$<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">source$<\/span>.<span style=\"color:#a6e22e\">pipe<\/span>(\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">exhaustMap<\/span>(<span style=\"color:#a6e22e\">sourceInstance<\/span> <span style=\"color:#f92672\">=&gt;<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#a6e22e\">resolveEffectSource<\/span>(\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">errorHandler<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">effectsErrorHandler<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>    )(<span style=\"color:#a6e22e\">sourceInstance<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>  }),\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#75715e\">\/* ... *\/<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>)\n<\/span><\/span><\/code><\/pre><\/div><p><code>resolveEffectSource<\/code> will merge all the existing properties (which are observables, possibly created by <code>createEffect()<\/code>) of the current instance and will eventually call the <code>ngrxOnRunEffects<\/code>lifecycle method(required by the <code>OnRunEffects<\/code> interface):<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">function<\/span> <span style=\"color:#a6e22e\">resolveEffectSource<\/span>(<span style=\"color:#75715e\">\/* ... *\/<\/span>)<span style=\"color:#f92672\">:<\/span> (<span style=\"color:#a6e22e\">sourceInstance<\/span>: <span style=\"color:#66d9ef\">any<\/span>) <span style=\"color:#f92672\">=&gt;<\/span> <span style=\"color:#a6e22e\">Observable<\/span>&lt;<span style=\"color:#f92672\">EffectNotification<\/span>&gt; {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#a6e22e\">sourceInstance<\/span> <span style=\"color:#f92672\">=&gt;<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">mergedEffects$<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">mergeEffects<\/span>(\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#a6e22e\">sourceInstance<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#a6e22e\">errorHandler<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#a6e22e\">effectsErrorHandler<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>    );\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#a6e22e\">isOnRunEffects<\/span>(<span style=\"color:#a6e22e\">sourceInstance<\/span>)) {\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#a6e22e\">sourceInstance<\/span>.<span style=\"color:#a6e22e\">ngrxOnRunEffects<\/span>(<span style=\"color:#a6e22e\">mergedEffects$<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>    }\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#a6e22e\">mergedEffects$<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>  };\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p>With <code>ngrxOnRunEffects<\/code> we can alter the <strong>observable resulted<\/strong> from <strong>merging<\/strong> all the <strong>effects<\/strong>(the instance&rsquo;s properties).<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">export<\/span> <span style=\"color:#66d9ef\">function<\/span> <span style=\"color:#a6e22e\">mergeEffects<\/span>(\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">sourceInstance<\/span>: <span style=\"color:#66d9ef\">any<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">globalErrorHandler<\/span>: <span style=\"color:#66d9ef\">ErrorHandler<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">effectsErrorHandler<\/span>: <span style=\"color:#66d9ef\">EffectsErrorHandler<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>)<span style=\"color:#f92672\">:<\/span> <span style=\"color:#a6e22e\">Observable<\/span>&lt;<span style=\"color:#f92672\">EffectNotification<\/span>&gt; {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">sourceName<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">getSourceForInstance<\/span>(<span style=\"color:#a6e22e\">sourceInstance<\/span>).<span style=\"color:#66d9ef\">constructor<\/span>.<span style=\"color:#a6e22e\">name<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#75715e\">\/\/ `getSourceMetadata(sourceInstance)` - getting all the effect class&#39; properties\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>  <span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">observables$<\/span>: <span style=\"color:#66d9ef\">Observable<\/span>&lt;<span style=\"color:#f92672\">any<\/span>&gt;[] <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">getSourceMetadata<\/span>(<span style=\"color:#a6e22e\">sourceInstance<\/span>).<span style=\"color:#a6e22e\">map<\/span>(\n<\/span><\/span><span style=\"display:flex;\"><span>    ({\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#a6e22e\">propertyName<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#a6e22e\">dispatch<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#a6e22e\">useEffectsErrorHandler<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>    })<span style=\"color:#f92672\">:<\/span> <span style=\"color:#a6e22e\">Observable<\/span>&lt;<span style=\"color:#f92672\">EffectNotification<\/span>&gt; <span style=\"color:#f92672\">=&gt;<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">observable$<\/span>: <span style=\"color:#66d9ef\">Observable<\/span>&lt;<span style=\"color:#f92672\">any<\/span>&gt; <span style=\"color:#f92672\">=<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#66d9ef\">typeof<\/span> <span style=\"color:#a6e22e\">sourceInstance<\/span>[<span style=\"color:#a6e22e\">propertyName<\/span>] <span style=\"color:#f92672\">===<\/span> <span style=\"color:#e6db74\">&#39;function&#39;<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>          <span style=\"color:#f92672\">?<\/span> <span style=\"color:#a6e22e\">sourceInstance<\/span>[<span style=\"color:#a6e22e\">propertyName<\/span>]()\n<\/span><\/span><span style=\"display:flex;\"><span>          <span style=\"color:#f92672\">:<\/span> <span style=\"color:#a6e22e\">sourceInstance<\/span>[<span style=\"color:#a6e22e\">propertyName<\/span>];\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#75715e\">\/\/ Whether it should re-subscribe if errors occur\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>      <span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">effectAction$<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">useEffectsErrorHandler<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#f92672\">?<\/span> <span style=\"color:#a6e22e\">effectsErrorHandler<\/span>(<span style=\"color:#a6e22e\">observable$<\/span>, <span style=\"color:#a6e22e\">globalErrorHandler<\/span>)\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#f92672\">:<\/span> <span style=\"color:#a6e22e\">observable$<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#75715e\">\/\/ You might not want the `Store` to intercept the action\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>      <span style=\"color:#75715e\">\/\/ and trigger state changes based on it\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>      <span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#a6e22e\">dispatch<\/span> <span style=\"color:#f92672\">===<\/span> <span style=\"color:#66d9ef\">false<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#a6e22e\">effectAction$<\/span>.<span style=\"color:#a6e22e\">pipe<\/span>(<span style=\"color:#a6e22e\">ignoreElements<\/span>());\n<\/span><\/span><span style=\"display:flex;\"><span>      }\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">materialized$<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">effectAction$<\/span>.<span style=\"color:#a6e22e\">pipe<\/span>(<span style=\"color:#a6e22e\">materialize<\/span>());\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#a6e22e\">materialized$<\/span>.<span style=\"color:#a6e22e\">pipe<\/span>(\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#a6e22e\">map<\/span>(<span style=\"color:#75715e\">\/* ... *\/<\/span>)\n<\/span><\/span><span style=\"display:flex;\"><span>      );\n<\/span><\/span><span style=\"display:flex;\"><span>    }\n<\/span><\/span><span style=\"display:flex;\"><span>  );\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#a6e22e\">merge<\/span>(...<span style=\"color:#a6e22e\">observables$<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p>A smaller example that reproduces the merging operation can be found <a href=\"https:\/\/stackblitz.com\/edit\/typescript-fv3us6?file=index.ts\" target=\"_blank\" rel=\"noopener\">here<\/a>.<\/p>\n<p>What <code>const materialized$ = effectAction$.pipe(materialize())<\/code> does is to make sure that if the re-subscription on error does <strong>not<\/strong> occur, it will <strong>suppress<\/strong> any incoming <strong>errors<\/strong>, meaning that the stream of all the merged effects won&rsquo;t be broken.<\/p>\n<p>At this stage, after all the effect class&rsquo; properties are merged into one observable, the <code>ngrxOnInitEffects<\/code> lifecycle method (required by the <code>OnInitEffects<\/code> interface) will be called for each class (if it exists) so that an <strong>action<\/strong> will be <strong>dispatched immediately<\/strong> and <strong>once<\/strong>:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">mergeMap<\/span>(<span style=\"color:#a6e22e\">source$<\/span> <span style=\"color:#f92672\">=&gt;<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#75715e\">\/\/ Merged effects\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>    <span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">effect$<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">source$<\/span>.<span style=\"color:#a6e22e\">pipe<\/span>(\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#a6e22e\">exhaustMap<\/span>(<span style=\"color:#75715e\">\/* ... *\/<\/span>),\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#75715e\">\/* ... *\/<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>    );\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#75715e\">\/\/ `source$`&#39;s value is an effect class instance\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>    <span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">init$<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">source$<\/span>.<span style=\"color:#a6e22e\">pipe<\/span>(\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#75715e\">\/\/ `take(1)` -&gt; make sure the `exhaustMap`&#39;s behavior is `replicated`\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>      <span style=\"color:#75715e\">\/\/ as there is only one effect class per identifier\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>      <span style=\"color:#a6e22e\">take<\/span>(<span style=\"color:#ae81ff\">1<\/span>),  \n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#a6e22e\">filter<\/span>(<span style=\"color:#a6e22e\">isOnInitEffects<\/span>),\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#75715e\">\/\/ `instance.ngrxOnInitEffects()` -&gt; Action\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>      <span style=\"color:#a6e22e\">map<\/span>(<span style=\"color:#a6e22e\">instance<\/span> <span style=\"color:#f92672\">=&gt;<\/span> <span style=\"color:#a6e22e\">instance<\/span>.<span style=\"color:#a6e22e\">ngrxOnInitEffects<\/span>())\n<\/span><\/span><span style=\"display:flex;\"><span>    );\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#a6e22e\">merge<\/span>(<span style=\"color:#a6e22e\">effect$<\/span>, <span style=\"color:#a6e22e\">init$<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>})\n<\/span><\/span><\/code><\/pre><\/div><p>The above process could be visualized as follows:<\/p>\n\n\n    \n    <div style=\"position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;\">\n      <iframe allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share\" allowfullscreen=\"allowfullscreen\" loading=\"eager\" referrerpolicy=\"strict-origin-when-cross-origin\" src=\"https:\/\/www.youtube.com\/embed\/k1bUKnNZO6g?autoplay=0&controls=1&end=0&loop=0&mute=0&start=0\" style=\"position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;\" title=\"YouTube video\"\n      ><\/iframe>\n    <\/div>\n\n<h2 id=\"creating-effects\">\n  <span>\n  Creating Effects\n  <\/span>\n  <a href=\"#creating-effects\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><p>Creating an <strong>effect<\/strong> can be achieved with the <code>createEffect()<\/code> function:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">type<\/span> <span style=\"color:#a6e22e\">DispatchType<\/span>&lt;<span style=\"color:#f92672\">T<\/span>&gt; <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">T<\/span> <span style=\"color:#66d9ef\">extends<\/span> { <span style=\"color:#a6e22e\">dispatch<\/span>: <span style=\"color:#66d9ef\">infer<\/span> <span style=\"color:#a6e22e\">U<\/span> } <span style=\"color:#f92672\">?<\/span> <span style=\"color:#a6e22e\">U<\/span> : <span style=\"color:#66d9ef\">true<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">type<\/span> <span style=\"color:#a6e22e\">ObservableType<\/span>&lt;<span style=\"color:#f92672\">T<\/span><span style=\"color:#960050;background-color:#1e0010\">,<\/span> <span style=\"color:#a6e22e\">OriginalType<\/span>&gt; <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">T<\/span> <span style=\"color:#66d9ef\">extends<\/span> <span style=\"color:#66d9ef\">false<\/span> <span style=\"color:#f92672\">?<\/span> <span style=\"color:#a6e22e\">OriginalType<\/span> : <span style=\"color:#66d9ef\">Action<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">export<\/span> <span style=\"color:#66d9ef\">function<\/span> <span style=\"color:#a6e22e\">createEffect<\/span><span style=\"color:#f92672\">&lt;<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">C<\/span> <span style=\"color:#66d9ef\">extends<\/span> <span style=\"color:#a6e22e\">EffectConfig<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">DT<\/span> <span style=\"color:#66d9ef\">extends<\/span> <span style=\"color:#a6e22e\">DispatchType<\/span>&lt;<span style=\"color:#f92672\">C<\/span>&gt;,\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">OT<\/span> <span style=\"color:#66d9ef\">extends<\/span> <span style=\"color:#a6e22e\">ObservableType<\/span>&lt;<span style=\"color:#f92672\">DT<\/span><span style=\"color:#960050;background-color:#1e0010\">,<\/span> <span style=\"color:#a6e22e\">OT<\/span>&gt;,\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">R<\/span> <span style=\"color:#66d9ef\">extends<\/span> <span style=\"color:#a6e22e\">Observable<\/span>&lt;<span style=\"color:#f92672\">OT<\/span>&gt; <span style=\"color:#f92672\">|<\/span> ((...<span style=\"color:#a6e22e\">args<\/span>: <span style=\"color:#66d9ef\">any<\/span>[]) <span style=\"color:#f92672\">=&gt;<\/span> <span style=\"color:#a6e22e\">Observable<\/span>&lt;<span style=\"color:#f92672\">OT<\/span>&gt;)\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#f92672\">&gt;<\/span>(<span style=\"color:#a6e22e\">source<\/span><span style=\"color:#f92672\">:<\/span> () <span style=\"color:#f92672\">=&gt;<\/span> <span style=\"color:#a6e22e\">R<\/span>, <span style=\"color:#a6e22e\">config?<\/span>: <span style=\"color:#66d9ef\">Partial<\/span>&lt;<span style=\"color:#f92672\">C<\/span>&gt;)<span style=\"color:#f92672\">:<\/span> <span style=\"color:#a6e22e\">R<\/span> <span style=\"color:#f92672\">&amp;<\/span> <span style=\"color:#a6e22e\">CreateEffectMetadata<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">effect<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">source<\/span>();\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">value<\/span>: <span style=\"color:#66d9ef\">EffectConfig<\/span> <span style=\"color:#f92672\">=<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>    ...<span style=\"color:#a6e22e\">DEFAULT_EFFECT_CONFIG<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>    ...<span style=\"color:#a6e22e\">config<\/span>, <span style=\"color:#75715e\">\/\/ Overrides any defaults if values are provided\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>  };\n<\/span><\/span><span style=\"display:flex;\"><span>  Object.<span style=\"color:#a6e22e\">defineProperty<\/span>(<span style=\"color:#a6e22e\">effect<\/span>, <span style=\"color:#a6e22e\">CREATE_EFFECT_METADATA_KEY<\/span>, {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">value<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  });\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#a6e22e\">effect<\/span> <span style=\"color:#66d9ef\">as<\/span> <span style=\"color:#66d9ef\">typeof<\/span> <span style=\"color:#a6e22e\">effect<\/span> <span style=\"color:#f92672\">&amp;<\/span> <span style=\"color:#a6e22e\">CreateEffectMetadata<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p><code>createEffect()<\/code> will return an <strong>observable<\/strong> with a property <code>CREATE_EFFECT_METADATA_KEY<\/code> attached to it which will hold the <strong>configuration object<\/strong> for that particular effect. When the merging of the effects class&rsquo; properties into one observable takes place, each observable(property of that effect class) will be slightly altered, depending on the configuration. This object can have 2 properties:<\/p>\n<ul>\n<li><code>dispatch: boolean<\/code> - whether the resulting action should be dispatched to the store or not;<\/li>\n<\/ul>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">observable$<\/span>: <span style=\"color:#66d9ef\">Observable<\/span>&lt;<span style=\"color:#f92672\">any<\/span>&gt; <span style=\"color:#f92672\">=<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">typeof<\/span> <span style=\"color:#a6e22e\">sourceInstance<\/span>[<span style=\"color:#a6e22e\">propertyName<\/span>] <span style=\"color:#f92672\">===<\/span> <span style=\"color:#e6db74\">&#39;function&#39;<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#f92672\">?<\/span> <span style=\"color:#a6e22e\">sourceInstance<\/span>[<span style=\"color:#a6e22e\">propertyName<\/span>]()\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#f92672\">:<\/span> <span style=\"color:#a6e22e\">sourceInstance<\/span>[<span style=\"color:#a6e22e\">propertyName<\/span>];\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">effectAction$<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">useEffectsErrorHandler<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#f92672\">?<\/span> <span style=\"color:#a6e22e\">effectsErrorHandler<\/span>(<span style=\"color:#a6e22e\">observable$<\/span>, <span style=\"color:#a6e22e\">globalErrorHandler<\/span>)\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#f92672\">:<\/span> <span style=\"color:#a6e22e\">observable$<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#a6e22e\">dispatch<\/span> <span style=\"color:#f92672\">===<\/span> <span style=\"color:#66d9ef\">false<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#a6e22e\">effectAction$<\/span>.<span style=\"color:#a6e22e\">pipe<\/span>(<span style=\"color:#a6e22e\">ignoreElements<\/span>());\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p>The <code>ignoreElements<\/code> operator will ignore everything, <strong>except error<\/strong> or <strong>complete<\/strong> notifications.<\/p>\n<ul>\n<li><code>useEffectsErrorHandler: boolean<\/code> - whether effect&rsquo;s errors(e.g: due to external API calls) should be handled or not;<\/li>\n<\/ul>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">observable$<\/span>: <span style=\"color:#66d9ef\">Observable<\/span>&lt;<span style=\"color:#f92672\">any<\/span>&gt; <span style=\"color:#f92672\">=<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">typeof<\/span> <span style=\"color:#a6e22e\">sourceInstance<\/span>[<span style=\"color:#a6e22e\">propertyName<\/span>] <span style=\"color:#f92672\">===<\/span> <span style=\"color:#e6db74\">&#39;function&#39;<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#f92672\">?<\/span> <span style=\"color:#a6e22e\">sourceInstance<\/span>[<span style=\"color:#a6e22e\">propertyName<\/span>]()\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#f92672\">:<\/span> <span style=\"color:#a6e22e\">sourceInstance<\/span>[<span style=\"color:#a6e22e\">propertyName<\/span>];\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">effectAction$<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">useEffectsErrorHandler<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#f92672\">?<\/span> <span style=\"color:#a6e22e\">effectsErrorHandler<\/span>(<span style=\"color:#a6e22e\">observable$<\/span>, <span style=\"color:#a6e22e\">globalErrorHandler<\/span>)\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#f92672\">:<\/span> <span style=\"color:#a6e22e\">observable$<\/span>;\n<\/span><\/span><\/code><\/pre><\/div><p><code>effectsErrorHandler<\/code> maps to a value provided by the <code>EFFECTS_ERROR_HANDLER<\/code>. By default, it maps to <code>defaultEffectsErrorHandler<\/code>(the built-in error handler for effects):<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">export<\/span> <span style=\"color:#66d9ef\">function<\/span> <span style=\"color:#a6e22e\">defaultEffectsErrorHandler<\/span>&lt;<span style=\"color:#f92672\">T<\/span> <span style=\"color:#a6e22e\">extends<\/span> <span style=\"color:#a6e22e\">Action<\/span>&gt;(\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">observable$<\/span>: <span style=\"color:#66d9ef\">Observable<\/span>&lt;<span style=\"color:#f92672\">T<\/span>&gt;,\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">errorHandler<\/span>: <span style=\"color:#66d9ef\">ErrorHandler<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">retryAttemptLeft<\/span>: <span style=\"color:#66d9ef\">number<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">MAX_NUMBER_OF_RETRY_ATTEMPTS<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>)<span style=\"color:#f92672\">:<\/span> <span style=\"color:#a6e22e\">Observable<\/span>&lt;<span style=\"color:#f92672\">T<\/span>&gt; {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#a6e22e\">observable$<\/span>.<span style=\"color:#a6e22e\">pipe<\/span>(\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">catchError<\/span>(<span style=\"color:#a6e22e\">error<\/span> <span style=\"color:#f92672\">=&gt;<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#a6e22e\">errorHandler<\/span>) <span style=\"color:#a6e22e\">errorHandler<\/span>.<span style=\"color:#a6e22e\">handleError<\/span>(<span style=\"color:#a6e22e\">error<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#a6e22e\">retryAttemptLeft<\/span> <span style=\"color:#f92672\">&lt;=<\/span> <span style=\"color:#ae81ff\">1<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#a6e22e\">observable$<\/span>; <span style=\"color:#75715e\">\/\/ last attempt\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>      }\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#75715e\">\/\/ Return observable that produces this particular effect\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>      <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#a6e22e\">defaultEffectsErrorHandler<\/span>(\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#a6e22e\">observable$<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#a6e22e\">errorHandler<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#a6e22e\">retryAttemptLeft<\/span> <span style=\"color:#f92672\">-<\/span> <span style=\"color:#ae81ff\">1<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>      );\n<\/span><\/span><span style=\"display:flex;\"><span>    })\n<\/span><\/span><span style=\"display:flex;\"><span>  );\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><blockquote>\n<p>If you&rsquo;d like to know why there must a limit regarding the number of retries, <a href=\"https:\/\/github.com\/ngrx\/platform\/issues\/2303\" target=\"_blank\" rel=\"noopener\">here&rsquo;s<\/a> the issue where this topic is addressed.<\/p>\n<\/blockquote>\n<p>When an error occurs, the observable will be unsubscribed. What <code>defaultEffectsErrorHandler<\/code> does is to allow us to re-subscribe to the _just-unsubscribed_observable as long as the maximum number of allowed attempts is not exceeded.<\/p>\n<p>For instance, if you have this effect:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">addUser$<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">createEffect<\/span>(\n<\/span><\/span><span style=\"display:flex;\"><span>  () <span style=\"color:#f92672\">=&gt;<\/span> <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">actions$<\/span>.<span style=\"color:#a6e22e\">pipe<\/span>(\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">ofType<\/span>(<span style=\"color:#a6e22e\">UserAction<\/span>.<span style=\"color:#a6e22e\">add<\/span>),\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">exhaustMap<\/span>(<span style=\"color:#a6e22e\">u<\/span> <span style=\"color:#f92672\">=&gt;<\/span> <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">userService<\/span>.<span style=\"color:#a6e22e\">add<\/span>(<span style=\"color:#a6e22e\">u<\/span>)),\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">map<\/span>(<span style=\"color:#75715e\">\/* Map to action *\/<\/span>)\n<\/span><\/span><span style=\"display:flex;\"><span>  ),\n<\/span><\/span><span style=\"display:flex;\"><span>)\n<\/span><\/span><\/code><\/pre><\/div><p>If an error occurs due to calling <code>userService.add()<\/code> and it is not handled anywhere, like:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ `this.userService.add(u)` is a cold observable\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span><span style=\"color:#a6e22e\">exhaustMap<\/span>(\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">u<\/span> <span style=\"color:#f92672\">=&gt;<\/span> <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">userService<\/span>.<span style=\"color:#a6e22e\">add<\/span>(<span style=\"color:#a6e22e\">u<\/span>).<span style=\"color:#a6e22e\">pipe<\/span>(<span style=\"color:#a6e22e\">catchError<\/span>(<span style=\"color:#a6e22e\">err<\/span> <span style=\"color:#f92672\">=&gt;<\/span> <span style=\"color:#75715e\">\/* Action *\/<\/span>))\n<\/span><\/span><span style=\"display:flex;\"><span>),\n<\/span><\/span><\/code><\/pre><\/div><p><code>addUser$<\/code> will unsubscribe from the <code>actions$<\/code> stream. <code>defaultEffectsErrorHandler<\/code> will simply re-subscribe to <code>actions$<\/code>, but there&rsquo;s another thing that&rsquo;s worth mentioning: the <code>actions$<\/code> stream is actually a <code>Subject<\/code> so we know for sure that when re-subscribed, we won&rsquo;t receive any of the previously emitted values, only the newer ones.<\/p>\n<p>You can also provide <strong>custom error handlers<\/strong> for effects:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span>{\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">provide<\/span>: <span style=\"color:#66d9ef\">EFFECTS_ERROR_HANDLER<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">useValue<\/span>: <span style=\"color:#66d9ef\">customErrHandler<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>},\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">function<\/span> <span style=\"color:#a6e22e\">customErrHandler<\/span> (<span style=\"color:#a6e22e\">obs$<\/span>, <span style=\"color:#a6e22e\">handler<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#a6e22e\">obs$<\/span>.<span style=\"color:#a6e22e\">pipe<\/span>(\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">catchError<\/span>((<span style=\"color:#a6e22e\">err<\/span>, <span style=\"color:#a6e22e\">caught$<\/span>) <span style=\"color:#f92672\">=&gt;<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#a6e22e\">console<\/span>.<span style=\"color:#a6e22e\">log<\/span>(<span style=\"color:#e6db74\">&#39;caught!&#39;<\/span>)\n<\/span><\/span><span style=\"display:flex;\"><span>      \n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#75715e\">\/\/ Only re-subscribe once\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>      <span style=\"color:#75715e\">\/\/ return obs$;\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#75715e\">\/\/ Re-subscribe every time an error occurs\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>      <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#a6e22e\">caught$<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>    }),\n<\/span><\/span><span style=\"display:flex;\"><span>  )\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p>where <code>customErrHandler<\/code> should be a function that accepts an <code>observable$<\/code>(the observable built on top of the <code>action$<\/code> observable) and an <code>errHandler<\/code> object.<\/p>\n<h2 id=\"typescripts-magic\">\n  <span>\n  TypeScript&rsquo;s Magic\n  <\/span>\n  <a href=\"#typescripts-magic\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><p>Now we are going to see the important role that TypeScript plays when it comes to creating effects using <code>createEffect<\/code>.<\/p>\n<p>Consider this effect:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">addUser$<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">createEffect<\/span>(\n<\/span><\/span><span style=\"display:flex;\"><span>  () <span style=\"color:#f92672\">=&gt;<\/span> <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">actions$<\/span>.<span style=\"color:#a6e22e\">pipe<\/span>(<span style=\"color:#75715e\">\/* ... *\/<\/span>),\n<\/span><\/span><span style=\"display:flex;\"><span>)\n<\/span><\/span><\/code><\/pre><\/div><p>The <code>addUser$<\/code>&rsquo;s type should be: <code>Observable&lt;Action&gt; &amp; CreateEffectMetadata<\/code>. <code>CreateEffectMetadata<\/code> is a way to identify a property created by <code>createEffect()<\/code>. It is particularly useful when the properties are merged into one single observable.<\/p>\n<p>Before revealing why <code>Observable&lt;Action&gt;<\/code> is there, let&rsquo;s try writing the same effect, but this time specifying the <code>dispatch: false<\/code>in the config object:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">addUser$<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">createEffect<\/span>(\n<\/span><\/span><span style=\"display:flex;\"><span>  () <span style=\"color:#f92672\">=&gt;<\/span> <span style=\"color:#66d9ef\">of<\/span>(<span style=\"color:#ae81ff\">1<\/span>),\n<\/span><\/span><span style=\"display:flex;\"><span>  { <span style=\"color:#a6e22e\">dispatch<\/span>: <span style=\"color:#66d9ef\">false<\/span> }\n<\/span><\/span><span style=\"display:flex;\"><span>)\n<\/span><\/span><\/code><\/pre><\/div><p><code>addUser$<\/code>&rsquo;s type will be <code>Observable&lt;number&gt; &amp; CreateEffectMetadata<\/code>.<\/p>\n<p>But if we have:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">addUser$<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">createEffect<\/span>(\n<\/span><\/span><span style=\"display:flex;\"><span>  () <span style=\"color:#f92672\">=&gt;<\/span> <span style=\"color:#66d9ef\">of<\/span>(<span style=\"color:#ae81ff\">1<\/span>),\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#75715e\">\/\/ { dispatch: false }\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>)\n<\/span><\/span><\/code><\/pre><\/div><p>we&rsquo;d get: <code>Type 'number' is not assignable to type 'Action'<\/code>. What this means is the the <code>dispatch<\/code> property has an <strong>influence<\/strong> on the <strong>effect&rsquo;s type<\/strong>.<\/p>\n<p>Let&rsquo;s see how this can be achieved:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ U defaults to `undefined` by default\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span><span style=\"color:#66d9ef\">type<\/span> <span style=\"color:#a6e22e\">DispatchType<\/span>&lt;<span style=\"color:#f92672\">T<\/span>&gt; <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">T<\/span> <span style=\"color:#66d9ef\">extends<\/span> { <span style=\"color:#a6e22e\">dispatch<\/span>: <span style=\"color:#66d9ef\">infer<\/span> <span style=\"color:#a6e22e\">U<\/span> } <span style=\"color:#f92672\">?<\/span> <span style=\"color:#a6e22e\">U<\/span> : <span style=\"color:#66d9ef\">true<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ `OriginalType` will be used only if the `dispatch` is explicitly set to `false`\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span><span style=\"color:#66d9ef\">type<\/span> <span style=\"color:#a6e22e\">ObservableType<\/span>&lt;<span style=\"color:#f92672\">T<\/span><span style=\"color:#960050;background-color:#1e0010\">,<\/span> <span style=\"color:#a6e22e\">OriginalType<\/span>&gt; <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">T<\/span> <span style=\"color:#66d9ef\">extends<\/span> <span style=\"color:#66d9ef\">false<\/span> <span style=\"color:#f92672\">?<\/span> <span style=\"color:#a6e22e\">OriginalType<\/span> : <span style=\"color:#66d9ef\">Action<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">export<\/span> <span style=\"color:#66d9ef\">function<\/span> <span style=\"color:#a6e22e\">createEffect<\/span><span style=\"color:#f92672\">&lt;<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">C<\/span> <span style=\"color:#66d9ef\">extends<\/span> <span style=\"color:#a6e22e\">EffectConfig<\/span>, <span style=\"color:#75715e\">\/\/ { dispatch?: boolean, useEffectsErrorHandler?: boolean; }\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>  <span style=\"color:#a6e22e\">DT<\/span> <span style=\"color:#66d9ef\">extends<\/span> <span style=\"color:#a6e22e\">DispatchType<\/span>&lt;<span style=\"color:#f92672\">C<\/span>&gt;, <span style=\"color:#75715e\">\/\/ U(undefined | boolean) || true\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>  <span style=\"color:#a6e22e\">OT<\/span> <span style=\"color:#66d9ef\">extends<\/span> <span style=\"color:#a6e22e\">ObservableType<\/span>&lt;<span style=\"color:#f92672\">DT<\/span><span style=\"color:#960050;background-color:#1e0010\">,<\/span> <span style=\"color:#a6e22e\">OT<\/span>&gt;, <span style=\"color:#75715e\">\/\/ If `DT` is false(`dispatch` explicitly set to `false`), use the original type\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>  <span style=\"color:#a6e22e\">R<\/span> <span style=\"color:#66d9ef\">extends<\/span> <span style=\"color:#a6e22e\">Observable<\/span>&lt;<span style=\"color:#f92672\">OT<\/span>&gt; <span style=\"color:#f92672\">|<\/span> ((...<span style=\"color:#a6e22e\">args<\/span>: <span style=\"color:#66d9ef\">any<\/span>[]) <span style=\"color:#f92672\">=&gt;<\/span> <span style=\"color:#a6e22e\">Observable<\/span>&lt;<span style=\"color:#f92672\">OT<\/span>&gt;) <span style=\"color:#75715e\">\/\/ Use `OT` to infer the Observable&#39;s type\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span><span style=\"color:#f92672\">&gt;<\/span>(<span style=\"color:#a6e22e\">source<\/span><span style=\"color:#f92672\">:<\/span> () <span style=\"color:#f92672\">=&gt;<\/span> <span style=\"color:#a6e22e\">R<\/span>, <span style=\"color:#a6e22e\">config?<\/span>: <span style=\"color:#66d9ef\">Partial<\/span>&lt;<span style=\"color:#f92672\">C<\/span>&gt;) { }\n<\/span><\/span><\/code><\/pre><\/div><p>With this in mind, in this snippet<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">addUser$<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">createEffect<\/span>(\n<\/span><\/span><span style=\"display:flex;\"><span>  () <span style=\"color:#f92672\">=&gt;<\/span> <span style=\"color:#66d9ef\">of<\/span>(<span style=\"color:#ae81ff\">1<\/span>),\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#75715e\">\/\/ { dispatch: false }\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>)\n<\/span><\/span><\/code><\/pre><\/div><p>we have(reading from the bottom):<\/p>\n<ul>\n<li><code>R<\/code> - <code>Observable&lt;number&gt;<\/code><\/li>\n<li><code>OT<\/code> - initially is of type <code>number<\/code><\/li>\n<li><code>DT<\/code> - <code>false<\/code> as <code>dispatch<\/code> is explicitly set to <code>false<\/code><\/li>\n<li><code>OT extends ObservableType&lt;DT, OT&gt;<\/code> determines the <em>final type<\/em> of <code>OT<\/code>: <code>false extends false ? number : Action<\/code> -&gt; we&rsquo;re getting <code>number<\/code><\/li>\n<\/ul>\n<p>Conversely, in this snippet<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">addUser$<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">createEffect<\/span>(\n<\/span><\/span><span style=\"display:flex;\"><span>  () <span style=\"color:#f92672\">=&gt;<\/span> <span style=\"color:#66d9ef\">of<\/span>(<span style=\"color:#ae81ff\">1<\/span>),\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#75715e\">\/\/ { dispatch: false }\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>)\n<\/span><\/span><\/code><\/pre><\/div><p>we have <code>OT extends ObservableType&lt;DT, OT&gt;<\/code> and it can be seen as <code>undefined extends false ? number : Action<\/code>. So, the <code>OT<\/code>&rsquo;s type will be <code>Action<\/code>, and we&rsquo;re getting the error because <code>addUser$<\/code>&rsquo;s type is <code>Observable&lt;number&gt;<\/code>, when it should&rsquo;ve been <code>Observable&lt;Action&gt;<\/code>.<\/p>\n<h2 id=\"the-actions-stream\">\n  <span>\n  The <code>actions$<\/code> stream\n  <\/span>\n  <a href=\"#the-actions-stream\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><p>Throughout the article you might have seen <code>actions$<\/code> several times. In this section we&rsquo;re going to find out what it is, what it does and how once again TypeScript ensures a seamless developer experience.<\/p>\n<p>Normally, you&rsquo;d inject the inject <code>actions$<\/code> \u00a0in an effects class this way:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">constructor<\/span>(<span style=\"color:#66d9ef\">private<\/span> <span style=\"color:#a6e22e\">actions$<\/span>: <span style=\"color:#66d9ef\">Actions<\/span>) {}\n<\/span><\/span><\/code><\/pre><\/div><div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">export<\/span> <span style=\"color:#66d9ef\">interface<\/span> <span style=\"color:#a6e22e\">Action<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">type<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#66d9ef\">string<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">@Injectable<\/span>()\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">export<\/span> <span style=\"color:#66d9ef\">class<\/span> <span style=\"color:#a6e22e\">Actions<\/span>&lt;<span style=\"color:#f92672\">V<\/span> <span style=\"color:#960050;background-color:#1e0010\">=<\/span> <span style=\"color:#a6e22e\">Action<\/span>&gt; <span style=\"color:#66d9ef\">extends<\/span> <span style=\"color:#a6e22e\">Observable<\/span>&lt;<span style=\"color:#f92672\">V<\/span>&gt; {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">constructor<\/span>(<span style=\"color:#66d9ef\">@Inject<\/span>(<span style=\"color:#a6e22e\">ScannedActionsSubject<\/span>) <span style=\"color:#a6e22e\">source?<\/span>: <span style=\"color:#66d9ef\">Observable<\/span>&lt;<span style=\"color:#f92672\">V<\/span>&gt;) {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">super<\/span>();\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#a6e22e\">source<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">source<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">source<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>    }\n<\/span><\/span><span style=\"display:flex;\"><span>  }\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">lift<\/span>&lt;<span style=\"color:#f92672\">R<\/span>&gt;(<span style=\"color:#a6e22e\">operator<\/span>: <span style=\"color:#66d9ef\">Operator<\/span>&lt;<span style=\"color:#f92672\">V<\/span><span style=\"color:#960050;background-color:#1e0010\">,<\/span> <span style=\"color:#a6e22e\">R<\/span>&gt;)<span style=\"color:#f92672\">:<\/span> <span style=\"color:#a6e22e\">Observable<\/span>&lt;<span style=\"color:#f92672\">R<\/span>&gt; {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">observable<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">new<\/span> <span style=\"color:#a6e22e\">Actions<\/span>&lt;<span style=\"color:#f92672\">R<\/span>&gt;();\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">observable<\/span>.<span style=\"color:#a6e22e\">source<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">this<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">observable<\/span>.<span style=\"color:#a6e22e\">operator<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">operator<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#a6e22e\">observable<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>  }\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p><code>ScannedActionsSubject<\/code> comes from <code>@ngrx\/store<\/code> and it is a <code>Subject<\/code>(thus, an <code>Observable<\/code>) that emits whenever actions are dispatched, but only <strong>after<\/strong> the <strong>state changes<\/strong> have been <strong>handled<\/strong>. So, when an action is dispatched(<code>Store.dispatch()<\/code>), the <code>State<\/code> entity will first update the application state depending on that action and the current state with the help of the reducers, then it will push that <code>action<\/code> into an <strong>actions stream<\/strong>, created by <code>ScannedActionsSubject<\/code>.<\/p>\n<p>By setting the <code>Actions<\/code>&rsquo; source to <code>ScannedActionsSubject<\/code>, every time we have something like <code>this.actions$.pipe().subscribe(observer)<\/code> the observer will be part of <code>ScannedActionsSubject<\/code>&rsquo;s observers list, meaning that when the subject emits an action(e.g: <code>subject.next(action)<\/code>), all the registered observers will receive it. This should explain why all the effects will receive the same actions, but, with <code>ofType<\/code>&rsquo;s help, these can be filtered out.<\/p>\n<p>Here&rsquo;s how the <code>ScannedActionsSubject<\/code> notifies its active observers:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ State\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span><span style=\"color:#75715e\">\/* ... *\/<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">stateAndAction$<\/span>: <span style=\"color:#66d9ef\">Observable<\/span><span style=\"color:#f92672\">&lt;<\/span>{\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">state<\/span>: <span style=\"color:#66d9ef\">any<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">action?<\/span>: <span style=\"color:#66d9ef\">Action<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>}<span style=\"color:#f92672\">&gt;<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">withLatestReducer$<\/span>.<span style=\"color:#a6e22e\">pipe<\/span>(\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">scan<\/span><span style=\"color:#f92672\">&lt;<\/span>[<span style=\"color:#a6e22e\">Action<\/span>, <span style=\"color:#a6e22e\">ActionReducer<\/span>&lt;<span style=\"color:#f92672\">T<\/span><span style=\"color:#960050;background-color:#1e0010\">,<\/span> <span style=\"color:#a6e22e\">Action<\/span>&gt;], <span style=\"color:#a6e22e\">StateActionPair<\/span>&lt;<span style=\"color:#f92672\">T<\/span>&gt;<span style=\"color:#f92672\">&gt;<\/span>(\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">reduceState<\/span>, <span style=\"color:#75715e\">\/\/ Handling state changes\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>    <span style=\"color:#a6e22e\">seed<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>  )\n<\/span><\/span><span style=\"display:flex;\"><span>);\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">stateSubscription<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">stateAndAction$<\/span>.<span style=\"color:#a6e22e\">subscribe<\/span>(({ <span style=\"color:#a6e22e\">state<\/span>, <span style=\"color:#a6e22e\">action<\/span> }) <span style=\"color:#f92672\">=&gt;<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">next<\/span>(<span style=\"color:#a6e22e\">state<\/span>); <span style=\"color:#75715e\">\/\/ `state` -&gt; the new state, after reducers have been invoked \n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>  <span style=\"color:#a6e22e\">scannedActions<\/span>.<span style=\"color:#a6e22e\">next<\/span>(<span style=\"color:#a6e22e\">action<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>});\n<\/span><\/span><\/code><\/pre><\/div><h2 id=\"oftype\">\n  <span>\n  <code>ofType<\/code>\n  <\/span>\n  <a href=\"#oftype\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><p>In order to determine which actions should trigger which effects, the <code>ofType<\/code> custom operator is used:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">export<\/span> <span style=\"color:#66d9ef\">function<\/span> <span style=\"color:#a6e22e\">ofType<\/span>(\n<\/span><\/span><span style=\"display:flex;\"><span>  ...<span style=\"color:#a6e22e\">allowedTypes<\/span>: <span style=\"color:#66d9ef\">Array<\/span>&lt;<span style=\"color:#f92672\">string<\/span> <span style=\"color:#960050;background-color:#1e0010\">|<\/span> <span style=\"color:#a6e22e\">ActionCreator<\/span><span style=\"color:#960050;background-color:#1e0010\">&lt;<\/span><span style=\"color:#a6e22e\">string<\/span><span style=\"color:#960050;background-color:#1e0010\">,<\/span> <span style=\"color:#a6e22e\">Creator<\/span>&gt;<span style=\"color:#f92672\">&gt;<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>)<span style=\"color:#f92672\">:<\/span> <span style=\"color:#a6e22e\">OperatorFunction<\/span>&lt;<span style=\"color:#f92672\">Action<\/span><span style=\"color:#960050;background-color:#1e0010\">,<\/span> <span style=\"color:#a6e22e\">Action<\/span>&gt; {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#a6e22e\">filter<\/span>((<span style=\"color:#a6e22e\">action<\/span>: <span style=\"color:#66d9ef\">Action<\/span>) <span style=\"color:#f92672\">=&gt;<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">allowedTypes<\/span>.<span style=\"color:#a6e22e\">some<\/span>(<span style=\"color:#a6e22e\">typeOrActionCreator<\/span> <span style=\"color:#f92672\">=&gt;<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#66d9ef\">typeof<\/span> <span style=\"color:#a6e22e\">typeOrActionCreator<\/span> <span style=\"color:#f92672\">===<\/span> <span style=\"color:#e6db74\">&#39;string&#39;<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#75715e\">\/\/ Comparing the string to type\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>        <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#a6e22e\">typeOrActionCreator<\/span> <span style=\"color:#f92672\">===<\/span> <span style=\"color:#a6e22e\">action<\/span>.<span style=\"color:#66d9ef\">type<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>      }\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#75715e\">\/\/ We are filtering by ActionCreator\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>      <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#a6e22e\">typeOrActionCreator<\/span>.<span style=\"color:#66d9ef\">type<\/span> <span style=\"color:#f92672\">===<\/span> <span style=\"color:#a6e22e\">action<\/span>.<span style=\"color:#66d9ef\">type<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>    })\n<\/span><\/span><span style=\"display:flex;\"><span>  );\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p>As you can see, it internally uses the RxJs <code>filter<\/code> operator, whose predicate function&rsquo;s return value depends on whether the current emitted action is among the values provided to <code>ofType<\/code>or not.<\/p>\n<p>What&rsquo;s indeed fascinating here is how <strong>TypeScript&rsquo;s power<\/strong> is leveraged.<\/p>\n<p>When it comes to <code>ofType<\/code>&rsquo;s type inference, there are 2 possibilities:<\/p>\n<ul>\n<li>you can provide actions created by <code>createAction()<\/code>, which complies with the <code>ActionCreator<\/code> type;<\/li>\n<\/ul>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">export<\/span> <span style=\"color:#66d9ef\">type<\/span> <span style=\"color:#a6e22e\">ActionCreator<\/span><span style=\"color:#f92672\">&lt;<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">T<\/span> <span style=\"color:#66d9ef\">extends<\/span> <span style=\"color:#66d9ef\">string<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">string<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">C<\/span> <span style=\"color:#66d9ef\">extends<\/span> <span style=\"color:#a6e22e\">Creator<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">Creator<\/span> <span style=\"color:#75715e\">\/\/ `Creator` -&gt; a function that returns an object\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span><span style=\"color:#f92672\">&gt;<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">C<\/span> <span style=\"color:#f92672\">&amp;<\/span> <span style=\"color:#a6e22e\">TypedAction<\/span>&lt;<span style=\"color:#f92672\">T<\/span>&gt;; <span style=\"color:#75715e\">\/\/ A function that has a readonly property `type`, which also returns an object\n<\/span><\/span><\/span><\/code><\/pre><\/div><p>By using <code>ofType(action1, action2, ...)<\/code>, its return type will be a union comprised of the return types of <code>action1<\/code>, <code>action2<\/code> and &hellip; <code>actionN<\/code>:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">export<\/span> <span style=\"color:#66d9ef\">function<\/span> <span style=\"color:#a6e22e\">ofType<\/span><span style=\"color:#f92672\">&lt;<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">AC<\/span> <span style=\"color:#66d9ef\">extends<\/span> <span style=\"color:#a6e22e\">ActionCreator<\/span>&lt;<span style=\"color:#f92672\">string<\/span><span style=\"color:#960050;background-color:#1e0010\">,<\/span> <span style=\"color:#a6e22e\">Creator<\/span>&gt;[],\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">U<\/span> <span style=\"color:#66d9ef\">extends<\/span> <span style=\"color:#a6e22e\">Action<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">Action<\/span>, <span style=\"color:#75715e\">\/\/ A created action\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>  <span style=\"color:#a6e22e\">V<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">ReturnType<\/span>&lt;<span style=\"color:#f92672\">AC<\/span><span style=\"color:#960050;background-color:#1e0010\">[<\/span><span style=\"color:#a6e22e\">number<\/span><span style=\"color:#960050;background-color:#1e0010\">]<\/span>&gt;\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#75715e\">\/\/ `U` - the type of the incoming observable\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>  <span style=\"color:#75715e\">\/\/ `V` - the type of the returned observable\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span><span style=\"color:#f92672\">&gt;<\/span>(...<span style=\"color:#a6e22e\">allowedTypes<\/span>: <span style=\"color:#66d9ef\">AC<\/span>)<span style=\"color:#f92672\">:<\/span> <span style=\"color:#a6e22e\">OperatorFunction<\/span>&lt;<span style=\"color:#f92672\">U<\/span><span style=\"color:#960050;background-color:#1e0010\">,<\/span> <span style=\"color:#a6e22e\">V<\/span>&gt;;\n<\/span><\/span><\/code><\/pre><\/div><p>What we&rsquo;re particularly interested in is the <code>V = ReturnType&lt;AC[number]&gt;<\/code> part. <code>AC<\/code> is an array of <code>ActionCreator<\/code>(results of <code>createAction<\/code>).<br>\n<code>AC[number]<\/code> will return a union of all the <code>AC<\/code>&rsquo;s elements. For example:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">type<\/span> <span style=\"color:#a6e22e\">Action<\/span>&lt;<span style=\"color:#f92672\">T<\/span> <span style=\"color:#a6e22e\">extends<\/span> <span style=\"color:#a6e22e\">string <\/span><span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">string<\/span>&gt; <span style=\"color:#f92672\">=<\/span> { <span style=\"color:#66d9ef\">readonly<\/span> <span style=\"color:#66d9ef\">type<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#a6e22e\">T<\/span>; }\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">function<\/span> <span style=\"color:#a6e22e\">createAction<\/span>&lt;<span style=\"color:#f92672\">P<\/span> <span style=\"color:#a6e22e\">extends<\/span> <span style=\"color:#a6e22e\">object<\/span><span style=\"color:#960050;background-color:#1e0010\">,<\/span> <span style=\"color:#a6e22e\">T<\/span> <span style=\"color:#a6e22e\">extends<\/span> <span style=\"color:#a6e22e\">string<\/span>&gt;(<span style=\"color:#a6e22e\">t<\/span>: <span style=\"color:#66d9ef\">T<\/span>, <span style=\"color:#a6e22e\">payload<\/span>: <span style=\"color:#66d9ef\">P<\/span>)<span style=\"color:#f92672\">:<\/span> <span style=\"color:#a6e22e\">P<\/span> <span style=\"color:#f92672\">&amp;<\/span> <span style=\"color:#a6e22e\">Action<\/span>&lt;<span style=\"color:#f92672\">T<\/span>&gt; {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">return<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>    ...<span style=\"color:#a6e22e\">payload<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">type<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#a6e22e\">t<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  };\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">actions<\/span> <span style=\"color:#f92672\">=<\/span> [<span style=\"color:#a6e22e\">createAction<\/span>(<span style=\"color:#e6db74\">&#39;type1&#39;<\/span>, { <span style=\"color:#a6e22e\">name<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;andrei&#39;<\/span> }), <span style=\"color:#a6e22e\">createAction<\/span>(<span style=\"color:#e6db74\">&#39;type2&#39;<\/span>, { <span style=\"color:#a6e22e\">age<\/span>: <span style=\"color:#66d9ef\">123<\/span> })];\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ `(typeof actions)[number]` -&gt; a union of types\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span><span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">action<\/span><span style=\"color:#f92672\">:<\/span> (<span style=\"color:#66d9ef\">typeof<\/span> <span style=\"color:#a6e22e\">actions<\/span>)[<span style=\"color:#66d9ef\">number<\/span>] <span style=\"color:#f92672\">=<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#75715e\">\/\/ We can discriminate unions with the help of the `type` property\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>  <span style=\"color:#75715e\">\/\/ because `createAction` returns an object with one `readonly` property,\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>  <span style=\"color:#75715e\">\/\/ namely `type`\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>  <span style=\"color:#66d9ef\">type<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;type2&#39;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">age<\/span>: <span style=\"color:#66d9ef\">123<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#75715e\">\/\/ name: &#39;John&#39; -&gt; ? error\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>}\n<\/span><\/span><\/code><\/pre><\/div><p>Similarly, the union resulted from <code>AC[number]<\/code> can be <strong>discriminated<\/strong> with the <code>type<\/code> property.<\/p>\n<p>Next, we have <code>ReturnType&lt;Union&gt;<\/code>. which is the same as <code>ReturnType&lt;Union_M1 | Union_M2 | ...&gt;<\/code>(where <code>Union_Mn<\/code> represents the <code>n-th<\/code><strong>member<\/strong> of the union). What it does is to determine the return type of each action. This union will be the type of the <code>ofType<\/code>&rsquo;s returned observable.<\/p>\n<ul>\n<li>you can provide <strong>strings<\/strong> that <strong>represent<\/strong> actual <strong>action types<\/strong>;<\/li>\n<\/ul>\n<p>However, since all that <code>ofType<\/code> is getting is a list of <strong>strings<\/strong>, in order to infer the right types, you must <strong>manually specify<\/strong> a <strong>union of types<\/strong> that are expected to match the provided action types.<\/p>\n<p>Let&rsquo;s take a look at one of the overloads of <code>Observable.pipe<\/code>:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">export<\/span> <span style=\"color:#66d9ef\">class<\/span> <span style=\"color:#a6e22e\">Observable<\/span>&lt;<span style=\"color:#f92672\">T<\/span>&gt; <span style=\"color:#66d9ef\">implements<\/span> <span style=\"color:#a6e22e\">Subscribable<\/span>&lt;<span style=\"color:#f92672\">T<\/span>&gt; {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#75715e\">\/* ... *\/<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>  \n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">pipe<\/span>&lt;<span style=\"color:#f92672\">A<\/span><span style=\"color:#960050;background-color:#1e0010\">,<\/span> <span style=\"color:#a6e22e\">B<\/span>&gt;(<span style=\"color:#a6e22e\">op1<\/span>: <span style=\"color:#66d9ef\">OperatorFunction<\/span>&lt;<span style=\"color:#f92672\">T<\/span><span style=\"color:#960050;background-color:#1e0010\">,<\/span> <span style=\"color:#a6e22e\">A<\/span>&gt;, <span style=\"color:#a6e22e\">op2<\/span>: <span style=\"color:#66d9ef\">OperatorFunction<\/span>&lt;<span style=\"color:#f92672\">A<\/span><span style=\"color:#960050;background-color:#1e0010\">,<\/span> <span style=\"color:#a6e22e\">B<\/span>&gt;)<span style=\"color:#f92672\">:<\/span> <span style=\"color:#a6e22e\">Observable<\/span>&lt;<span style=\"color:#f92672\">B<\/span>&gt;;\n<\/span><\/span><span style=\"display:flex;\"><span>  \n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#75715e\">\/* ... *\/<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p>where <code>OperatorFunction&lt;T,A&gt;<\/code> specifies the type of a function that <strong>receives<\/strong> an <strong>observable<\/strong> as a parameter and <strong>returns<\/strong> another <strong>observable<\/strong>:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">export<\/span> <span style=\"color:#66d9ef\">interface<\/span> <span style=\"color:#a6e22e\">UnaryFunction<\/span>&lt;<span style=\"color:#f92672\">T<\/span><span style=\"color:#960050;background-color:#1e0010\">,<\/span> <span style=\"color:#a6e22e\">R<\/span>&gt; { (<span style=\"color:#a6e22e\">source<\/span>: <span style=\"color:#66d9ef\">T<\/span>)<span style=\"color:#f92672\">:<\/span> <span style=\"color:#a6e22e\">R<\/span>; }\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">export<\/span> <span style=\"color:#66d9ef\">interface<\/span> <span style=\"color:#a6e22e\">OperatorFunction<\/span>&lt;<span style=\"color:#f92672\">T<\/span><span style=\"color:#960050;background-color:#1e0010\">,<\/span> <span style=\"color:#a6e22e\">R<\/span>&gt; <span style=\"color:#66d9ef\">extends<\/span> <span style=\"color:#a6e22e\">UnaryFunction<\/span>&lt;<span style=\"color:#f92672\">Observable<\/span><span style=\"color:#960050;background-color:#1e0010\">&lt;<\/span><span style=\"color:#a6e22e\">T<\/span>&gt;, <span style=\"color:#a6e22e\">Observable<\/span>&lt;<span style=\"color:#f92672\">R<\/span>&gt;<span style=\"color:#f92672\">&gt;<\/span> {}\n<\/span><\/span><\/code><\/pre><\/div><p>So, from the above snippets we can notice that the first operator in the <code>pipe<\/code> function will be a function whose single parameter&rsquo;s type will be an observable of type <code>T<\/code>(where <code>T<\/code> is the type parameter for <code>Observable<\/code>).<\/p>\n<p>With this in mind, let&rsquo;s take a look at the <code>Actions<\/code> class, which provides a stream of actions depending on which the effects will act:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">@Injectable<\/span>()\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">export<\/span> <span style=\"color:#66d9ef\">class<\/span> <span style=\"color:#a6e22e\">Actions<\/span>&lt;<span style=\"color:#f92672\">V<\/span> <span style=\"color:#960050;background-color:#1e0010\">=<\/span> <span style=\"color:#a6e22e\">Action<\/span>&gt; <span style=\"color:#66d9ef\">extends<\/span> <span style=\"color:#a6e22e\">Observable<\/span>&lt;<span style=\"color:#f92672\">V<\/span>&gt; {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">constructor<\/span>(<span style=\"color:#66d9ef\">@Inject<\/span>(<span style=\"color:#a6e22e\">ScannedActionsSubject<\/span>) <span style=\"color:#a6e22e\">source?<\/span>: <span style=\"color:#66d9ef\">Observable<\/span>&lt;<span style=\"color:#f92672\">V<\/span>&gt;) { }\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p>Interesting, so <code>Actions&lt;V = Action&gt;<\/code> is also an <code>Observable&lt;V&gt;<\/code>, which means that the parameter&rsquo;s type of first operator(function) in the <code>pipe<\/code> will be of type <code>V<\/code>.<\/p>\n<p>Let&rsquo;s also have a look at the other <code>ofType<\/code>&rsquo;s overloads:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">export<\/span> <span style=\"color:#66d9ef\">function<\/span> <span style=\"color:#a6e22e\">ofType<\/span><span style=\"color:#f92672\">&lt;<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">E<\/span> <span style=\"color:#66d9ef\">extends<\/span> <span style=\"color:#a6e22e\">Extract<\/span>&lt;<span style=\"color:#f92672\">U<\/span><span style=\"color:#960050;background-color:#1e0010\">,<\/span> { <span style=\"color:#a6e22e\">type<\/span><span style=\"color:#960050;background-color:#1e0010\">:<\/span> <span style=\"color:#a6e22e\">T1<\/span> }&gt;,\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">AC<\/span> <span style=\"color:#66d9ef\">extends<\/span> <span style=\"color:#a6e22e\">ActionCreator<\/span>&lt;<span style=\"color:#f92672\">string<\/span><span style=\"color:#960050;background-color:#1e0010\">,<\/span> <span style=\"color:#a6e22e\">Creator<\/span>&gt;,\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">T1<\/span> <span style=\"color:#66d9ef\">extends<\/span> <span style=\"color:#66d9ef\">string<\/span> <span style=\"color:#f92672\">|<\/span> <span style=\"color:#a6e22e\">AC<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">U<\/span> <span style=\"color:#66d9ef\">extends<\/span> <span style=\"color:#a6e22e\">Action<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">Action<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">V<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">T1<\/span> <span style=\"color:#66d9ef\">extends<\/span> <span style=\"color:#66d9ef\">string<\/span> <span style=\"color:#f92672\">?<\/span> <span style=\"color:#a6e22e\">E<\/span> : <span style=\"color:#66d9ef\">ReturnType<\/span>&lt;<span style=\"color:#f92672\">Extract<\/span><span style=\"color:#960050;background-color:#1e0010\">&lt;<\/span><span style=\"color:#a6e22e\">T1<\/span><span style=\"color:#960050;background-color:#1e0010\">,<\/span> <span style=\"color:#a6e22e\">AC<\/span>&gt;<span style=\"color:#f92672\">&gt;<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#f92672\">&gt;<\/span>(<span style=\"color:#a6e22e\">t1<\/span>: <span style=\"color:#66d9ef\">T1<\/span>)<span style=\"color:#f92672\">:<\/span> <span style=\"color:#a6e22e\">OperatorFunction<\/span>&lt;<span style=\"color:#f92672\">U<\/span><span style=\"color:#960050;background-color:#1e0010\">,<\/span> <span style=\"color:#a6e22e\">V<\/span>&gt;;\n<\/span><\/span><\/code><\/pre><\/div><p>Please disregard what&rsquo;s between <code>&lt;&gt;<\/code> for a moment in order to heed the <code>ofType<\/code>&rsquo;s return type, along with the type of the first operator in <code>Observable.pipe<\/code>:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">ofType<\/span>()<span style=\"color:#f92672\">:<\/span> <span style=\"color:#a6e22e\">OperatorFunction<\/span>&lt;<span style=\"color:#f92672\">U<\/span><span style=\"color:#960050;background-color:#1e0010\">,<\/span> <span style=\"color:#a6e22e\">V<\/span>&gt; <span style=\"color:#f92672\">&lt;---&gt;<\/span> <span style=\"color:#a6e22e\">pipe<\/span>&lt;<span style=\"color:#f92672\">A<\/span>&gt;(<span style=\"color:#a6e22e\">op1<\/span>: <span style=\"color:#66d9ef\">OperatorFunction<\/span>&lt;<span style=\"color:#f92672\">T<\/span><span style=\"color:#960050;background-color:#1e0010\">,<\/span> <span style=\"color:#a6e22e\">A<\/span>&gt;)\n<\/span><\/span><\/code><\/pre><\/div><p>What we can deduce from here is that the <code>U<\/code> type parameter of <code>ofType<\/code> will be <code>T<\/code>, namely, <code>V<\/code>(from <code>Actions&lt;V extends Action&gt; extends Observable&lt;V&gt;<\/code>).<\/p>\n<p>This is why you&rsquo;ll have to provide a union of actions when you inject the <code>Actions<\/code> observable in your effects class, otherwise it would be impossible to infer the return types of the actions the effect is interested in. By providing this union, we can now let TypeScript play its part.<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">export<\/span> <span style=\"color:#66d9ef\">function<\/span> <span style=\"color:#a6e22e\">ofType<\/span><span style=\"color:#f92672\">&lt;<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">E<\/span> <span style=\"color:#66d9ef\">extends<\/span> <span style=\"color:#a6e22e\">Extract<\/span>&lt;<span style=\"color:#f92672\">U<\/span><span style=\"color:#960050;background-color:#1e0010\">,<\/span> { <span style=\"color:#a6e22e\">type<\/span><span style=\"color:#960050;background-color:#1e0010\">:<\/span> <span style=\"color:#a6e22e\">T1<\/span> }&gt;,\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">AC<\/span> <span style=\"color:#66d9ef\">extends<\/span> <span style=\"color:#a6e22e\">ActionCreator<\/span>&lt;<span style=\"color:#f92672\">string<\/span><span style=\"color:#960050;background-color:#1e0010\">,<\/span> <span style=\"color:#a6e22e\">Creator<\/span>&gt;,\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">T1<\/span> <span style=\"color:#66d9ef\">extends<\/span> <span style=\"color:#66d9ef\">string<\/span> <span style=\"color:#f92672\">|<\/span> <span style=\"color:#a6e22e\">AC<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">U<\/span> <span style=\"color:#66d9ef\">extends<\/span> <span style=\"color:#a6e22e\">Action<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">Action<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">V<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">T1<\/span> <span style=\"color:#66d9ef\">extends<\/span> <span style=\"color:#66d9ef\">string<\/span> <span style=\"color:#f92672\">?<\/span> <span style=\"color:#a6e22e\">E<\/span> : <span style=\"color:#66d9ef\">ReturnType<\/span>&lt;<span style=\"color:#f92672\">Extract<\/span><span style=\"color:#960050;background-color:#1e0010\">&lt;<\/span><span style=\"color:#a6e22e\">T1<\/span><span style=\"color:#960050;background-color:#1e0010\">,<\/span> <span style=\"color:#a6e22e\">AC<\/span>&gt;<span style=\"color:#f92672\">&gt;<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#f92672\">&gt;<\/span>(<span style=\"color:#a6e22e\">t1<\/span>: <span style=\"color:#66d9ef\">T1<\/span>)<span style=\"color:#f92672\">:<\/span> <span style=\"color:#a6e22e\">OperatorFunction<\/span>&lt;<span style=\"color:#f92672\">U<\/span><span style=\"color:#960050;background-color:#1e0010\">,<\/span> <span style=\"color:#a6e22e\">V<\/span>&gt;;\n<\/span><\/span><\/code><\/pre><\/div><p>So, we&rsquo;ve established that <code>U<\/code> will be the <code>V<\/code> type(<code>V<\/code> of the <code>Actions&lt;V = Action&gt;<\/code>), which, when injected, it will equal to the provided union of actions.<br>\n<code>E<\/code> will be the <strong>extracted action<\/strong>, based on the <strong>singleton type<\/strong>(the <code>type<\/code> property). As we know, an action(created by <code>createAction<\/code>) is a function that has a readonly property called <code>type<\/code>. This will allow us to infer the real action(which is part of the union <code>V<\/code> of the injected <code>Actions&lt;V&gt;<\/code>), because every action extends <code>&lt;{ type: aSingletonType }&gt;<\/code>.<br>\nFinally, the return type will be <code>V<\/code>(<code>V<\/code> of <code>ofType<\/code>), whose value is based on a binary decision:<\/p>\n<ul>\n<li><code>E<\/code>(the inferred <strong>created<\/strong> action), because <code>T1<\/code> is a <strong>singleton type<\/strong> which will allow TypeScript to infer the actual action;<\/li>\n<\/ul>\n<p>Here&rsquo;s an example that mimics this behavior:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ Can be thought of as actions\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span><span style=\"color:#66d9ef\">type<\/span> <span style=\"color:#a6e22e\">A<\/span> <span style=\"color:#f92672\">=<\/span> { <span style=\"color:#66d9ef\">type<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;andrei&#39;<\/span> };\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">type<\/span> <span style=\"color:#a6e22e\">J<\/span> <span style=\"color:#f92672\">=<\/span> { <span style=\"color:#66d9ef\">type<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;john&#39;<\/span> };\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">type<\/span> <span style=\"color:#a6e22e\">JA<\/span> <span style=\"color:#f92672\">=<\/span> { <span style=\"color:#66d9ef\">type<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;jane&#39;<\/span> };\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ E extends Extract&lt;U, { type: &#39;andrei&#39; | &#39;john&#39; | &#39;jane&#39; }&gt;,\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span><span style=\"color:#66d9ef\">type<\/span> <span style=\"color:#a6e22e\">Names<\/span> <span style=\"color:#f92672\">=<\/span> { <span style=\"color:#66d9ef\">type<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;andrei&#39;<\/span> <span style=\"color:#f92672\">|<\/span> <span style=\"color:#e6db74\">&#39;john&#39;<\/span> <span style=\"color:#f92672\">|<\/span> <span style=\"color:#e6db74\">&#39;jane&#39;<\/span> };\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ === `createAction(&#39;john&#39;, props&lt;{ age: number }&gt;())`\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span><span style=\"color:#66d9ef\">type<\/span> <span style=\"color:#a6e22e\">JSub<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">J<\/span> <span style=\"color:#f92672\">&amp;<\/span> { <span style=\"color:#a6e22e\">age<\/span>: <span style=\"color:#66d9ef\">number<\/span> };\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ === `createAction(&#39;john&#39;, props&lt;{ city: string }&gt;())`\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span><span style=\"color:#66d9ef\">type<\/span> <span style=\"color:#a6e22e\">ASub<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">A<\/span> <span style=\"color:#f92672\">&amp;<\/span> { <span style=\"color:#a6e22e\">city<\/span>: <span style=\"color:#66d9ef\">string<\/span> };\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">type<\/span> <span style=\"color:#a6e22e\">R<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">Extract<\/span>&lt;<span style=\"color:#f92672\">ASub<\/span> <span style=\"color:#960050;background-color:#1e0010\">|<\/span> <span style=\"color:#a6e22e\">JSub<\/span><span style=\"color:#960050;background-color:#1e0010\">,<\/span> <span style=\"color:#a6e22e\">A<\/span> <span style=\"color:#960050;background-color:#1e0010\">|<\/span> <span style=\"color:#a6e22e\">JA<\/span> <span style=\"color:#960050;background-color:#1e0010\">|<\/span> <span style=\"color:#a6e22e\">J<\/span>&gt;;\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">type<\/span> <span style=\"color:#a6e22e\">R2<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">Extract<\/span>&lt;<span style=\"color:#f92672\">ASub<\/span> <span style=\"color:#960050;background-color:#1e0010\">|<\/span> <span style=\"color:#a6e22e\">JSub<\/span><span style=\"color:#960050;background-color:#1e0010\">,<\/span> <span style=\"color:#a6e22e\">Names<\/span>&gt;;\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ After choosing the value of the `type` property\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ the unions will be discriminated\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span><span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">o<\/span>: <span style=\"color:#66d9ef\">R<\/span> <span style=\"color:#f92672\">=<\/span> { <span style=\"color:#66d9ef\">type<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;andrei&#39;<\/span>, <span style=\"color:#a6e22e\">city<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;city&#39;<\/span>, };\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">o2<\/span>: <span style=\"color:#66d9ef\">R2<\/span> <span style=\"color:#f92672\">=<\/span> { <span style=\"color:#66d9ef\">type<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;john&#39;<\/span>, <span style=\"color:#a6e22e\">age<\/span>: <span style=\"color:#66d9ef\">18<\/span> };\n<\/span><\/span><\/code><\/pre><\/div><p><em><a href=\"https:\/\/www.typescriptlang.org\/play\/#code\/PTAEGEEMDtQIwKagC4AsD2BXA5q5p0AzUSAZxIGNkBLdaUgKGQE8AHJAQVAF5QBvFGwQAuUAHIYAEwBOCamNABfANxMhoAFI9&#43;g9qLEArdKmgKVa9pq68BLPeIMwEZ1QxCgAoqAQAPZAmhJcg8-aUgqAB4AVQAaHTsRcSlZeVAAHwdjU3SHJzMAPhiLJAA5SABbBHIbXUSJQJSFDMMsptzoZyVXd25e0AADCllIfw4qWmgAChaTMTjWaXRWUgiBSGxE6ExyxGklfMmASkP&#43;4s0AZUw4bS0AMh11ze3drrcwXt5B4dHxummjWbzRbLVagCjUFiiUjIaTUaDYfZHE5nDiXa68Lj3ATgyGgaGw&#43;GvM4AJW0IRh4WQEVRVxyGjRcS4GQ0TM0&#43;VUCVAxIATGTQpTqWi6QzQGVKqR2Qw3qAOIR-HsKBh0KQ4Qi0EgAG6QAA2mCQRBQqCQ-QS-VACyWCGkLGl6tAmGgE3IAHdqNrtfAkJJqKQhtRynCRghJAwKHRoQRRKSagl9Mk5HMwRDmPoccxE&#43;Yw-R8OhuVHeTGhPoAaY4o9RABGAAcXSAA\" target=\"_blank\" rel=\"noopener\">TypeScript Playground<\/a>.<\/em><\/p>\n<ul>\n<li><code>ReturnType&lt;Extract&lt;T1, AC&gt;&gt;<\/code>, because the value of <code>T1<\/code> type is not a <strong>string subtype<\/strong>, it must be an <strong>action creator<\/strong>, so we only want to get its return type<\/li>\n<\/ul>\n<h2 id=\"connecting-ngrxeffects-with-ngrxstore\">\n  <span>\n  Connecting <code>ngrx\/effects<\/code> with <code>ngrx\/store<\/code>\n  <\/span>\n  <a href=\"#connecting-ngrxeffects-with-ngrxstore\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><p>Armed with the knowledge from this article and from <em><a href=\"https:\/\/andreigatej.dev\/blog\/ngrx-storemodule\/\">Understanding the magic behind StoreModule of NgRx (@ngrx\/store)<\/a><\/em>, we can now visualize what&rsquo;s happening behind the scenes:<\/p>\n\n\n    \n    <div style=\"position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;\">\n      <iframe allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share\" allowfullscreen=\"allowfullscreen\" loading=\"eager\" referrerpolicy=\"strict-origin-when-cross-origin\" src=\"https:\/\/www.youtube.com\/embed\/MS2YLYMVo3A?autoplay=0&controls=1&end=0&loop=0&mute=0&start=0\" style=\"position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;\" title=\"YouTube video\"\n      ><\/iframe>\n    <\/div>\n\n<ul>\n<li><code>Store.dispatch()<\/code><\/li>\n<\/ul>\n<p>It signals that an <strong>event<\/strong> that requires <strong>state changes<\/strong> is sent from the UI(e.g a smart component). <code>Store.dispatch()<\/code> will push the action(event) into an actions stream(which is different from the one that belongs to the <code>effects<\/code>):<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ Store\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span><span style=\"color:#a6e22e\">dispatch<\/span>(<span style=\"color:#a6e22e\">action<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">actionsObserver<\/span>.<span style=\"color:#a6e22e\">next<\/span>(<span style=\"color:#a6e22e\">action<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p>What&rsquo;s also worth mentioning here is that the <code>Store<\/code> class is an <strong>observable<\/strong> and its source is the <code>State<\/code>, which is also an observable, more precisely, a <code>BehaviorSubject<\/code>:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ Store\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span><span style=\"color:#66d9ef\">constructor<\/span>(\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">state$<\/span>: <span style=\"color:#66d9ef\">StateObservable<\/span>, <span style=\"color:#75715e\">\/\/ The `State` class\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>  <span style=\"color:#66d9ef\">private<\/span> <span style=\"color:#a6e22e\">actionsObserver<\/span>: <span style=\"color:#66d9ef\">ActionsSubject<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">super<\/span>();\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">source<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">state$<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>}   \n<\/span><\/span><\/code><\/pre><\/div><p>This is useful because components from the UI layer can simply subscribe to the Store class in order to be updated when state changes occur.<\/p>\n<ul>\n<li>Intercept the action in the <code>State<\/code> class<\/li>\n<\/ul>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ State\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span><span style=\"color:#66d9ef\">constructor<\/span>(\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">actions$<\/span>: <span style=\"color:#66d9ef\">ActionsSubject<\/span>, <span style=\"color:#75715e\">\/\/ Receive the actions dispatched from `Store`\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>  <span style=\"color:#a6e22e\">reducer$<\/span>: <span style=\"color:#66d9ef\">ReducerObservable<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">scannedActions<\/span>: <span style=\"color:#66d9ef\">ScannedActionsSubject<\/span>, <span style=\"color:#75715e\">\/\/ The `actions stream` that belong to effects\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>  <span style=\"color:#66d9ef\">@Inject<\/span>(<span style=\"color:#a6e22e\">INITIAL_STATE<\/span>) <span style=\"color:#a6e22e\">initialState<\/span>: <span style=\"color:#66d9ef\">any<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">actionsOnQueue$<\/span>: <span style=\"color:#66d9ef\">Observable<\/span>&lt;<span style=\"color:#f92672\">Action<\/span>&gt; <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">actions$<\/span>.<span style=\"color:#a6e22e\">pipe<\/span>(\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">observeOn<\/span>(<span style=\"color:#a6e22e\">queueScheduler<\/span>)\n<\/span><\/span><span style=\"display:flex;\"><span>  );\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">withLatestReducer$<\/span>: <span style=\"color:#66d9ef\">Observable<\/span><span style=\"color:#f92672\">&lt;<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>    [<span style=\"color:#a6e22e\">Action<\/span>, <span style=\"color:#a6e22e\">ActionReducer<\/span>&lt;<span style=\"color:#f92672\">any<\/span><span style=\"color:#960050;background-color:#1e0010\">,<\/span> <span style=\"color:#a6e22e\">Action<\/span>&gt;]\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#f92672\">&gt;<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">actionsOnQueue$<\/span>.<span style=\"color:#a6e22e\">pipe<\/span>(<span style=\"color:#a6e22e\">withLatestFrom<\/span>(<span style=\"color:#a6e22e\">reducer$<\/span>));\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">seed<\/span>: <span style=\"color:#66d9ef\">StateActionPair<\/span>&lt;<span style=\"color:#f92672\">T<\/span>&gt; <span style=\"color:#f92672\">=<\/span> { <span style=\"color:#a6e22e\">state<\/span>: <span style=\"color:#66d9ef\">initialState<\/span> };\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">stateAndAction$<\/span>: <span style=\"color:#66d9ef\">Observable<\/span><span style=\"color:#f92672\">&lt;<\/span>{\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">state<\/span>: <span style=\"color:#66d9ef\">any<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">action?<\/span>: <span style=\"color:#66d9ef\">Action<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>  }<span style=\"color:#f92672\">&gt;<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">withLatestReducer$<\/span>.<span style=\"color:#a6e22e\">pipe<\/span>(\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">scan<\/span><span style=\"color:#f92672\">&lt;<\/span>[<span style=\"color:#a6e22e\">Action<\/span>, <span style=\"color:#a6e22e\">ActionReducer<\/span>&lt;<span style=\"color:#f92672\">T<\/span><span style=\"color:#960050;background-color:#1e0010\">,<\/span> <span style=\"color:#a6e22e\">Action<\/span>&gt;], <span style=\"color:#a6e22e\">StateActionPair<\/span>&lt;<span style=\"color:#f92672\">T<\/span>&gt;<span style=\"color:#f92672\">&gt;<\/span>(\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#75715e\">\/\/ a)\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>      <span style=\"color:#a6e22e\">reduceState<\/span>, <span style=\"color:#75715e\">\/\/ Invoke the reducers -&gt; the result will be a new state\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>      <span style=\"color:#75715e\">\/\/ =====\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>      <span style=\"color:#a6e22e\">seed<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>    )\n<\/span><\/span><span style=\"display:flex;\"><span>  );\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">stateSubscription<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">stateAndAction$<\/span>.<span style=\"color:#a6e22e\">subscribe<\/span>(({ <span style=\"color:#a6e22e\">state<\/span>, <span style=\"color:#a6e22e\">action<\/span> }) <span style=\"color:#f92672\">=&gt;<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#75715e\">\/\/ b)\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>    <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">next<\/span>(<span style=\"color:#a6e22e\">state<\/span>); <span style=\"color:#75715e\">\/\/ Send the new state to the data consumer(e.g: a smart component)\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>    <span style=\"color:#75715e\">\/\/ =====\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#75715e\">\/\/ c)\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>    <span style=\"color:#a6e22e\">scannedActions<\/span>.<span style=\"color:#a6e22e\">next<\/span>(<span style=\"color:#a6e22e\">action<\/span>); <span style=\"color:#75715e\">\/\/ Notify effects that an action ocurred\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>    <span style=\"color:#75715e\">\/\/ =====\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>  });\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><ul>\n<li><code>a)<\/code>: call the <strong>reducers<\/strong> with the current action and the current state, resulting a new state<\/li>\n<li><code>b)<\/code> send the <strong>new state<\/strong> to the <strong>data consumers<\/strong>;<br>\nRemember that <code>State<\/code> is the source of <code>Store<\/code>, meaning that <code>this.next(state);<\/code> will make <code>state<\/code> accessible in the <code>Store<\/code>class, which can be subscribed to: <code>Store.select()<\/code> or <code>Store.pipe(select())<\/code><\/li>\n<li><code>c)<\/code>: after state changes have been handled and sent to the data consumers, send the action to the effects;<br>\nIf the action is intercepted by any of the registered effects, a <strong>new action<\/strong> will arise which will in turn be intercepted by the <code>Store()<\/code>, causing the steps <code>a), b), c)<\/code> to be repeated:<\/li>\n<\/ul>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">effectSources<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>  .<span style=\"color:#a6e22e\">toActions<\/span>() <span style=\"color:#75715e\">\/\/ The action resulted from all the merged effects \n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>  .<span style=\"color:#a6e22e\">subscribe<\/span>(<span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">store<\/span>);\n<\/span><\/span><\/code><\/pre><\/div><p>This is possible because the <code>Store<\/code> can act as a subscriber as well:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ Store\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span><span style=\"color:#a6e22e\">next<\/span>(<span style=\"color:#a6e22e\">action<\/span>: <span style=\"color:#66d9ef\">Action<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">actionsObserver<\/span>.<span style=\"color:#a6e22e\">next<\/span>(<span style=\"color:#a6e22e\">action<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p><strong><strong>That&rsquo;s it, folks! Thanks for reading!<\/strong><\/strong><\/p>\n"},{"title":"Understanding the magic behind StoreModule of NgRx (@ngrx\/store)","link":"https:\/\/andreigatej.dev\/blog\/ngrx-storemodule\/","pubDate":"Tue, 07 Apr 2020 00:00:00 +0000","guid":"https:\/\/andreigatej.dev\/blog\/ngrx-storemodule\/","description":"<p><em>This article has been published on <a href=\"https:\/\/indepth.dev\/posts\/1199\/understanding-the-magic-behind-ngrx-store\" target=\"_blank\" rel=\"noopener\">indepth.dev<\/a>.<\/em><\/p>\n<h2 id=\"introduction\">\n  <span>\n  Introduction\n  <\/span>\n  <a href=\"#introduction\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><p>I was writing this article as I was going through the source code trying to understand how the main entities of the <code>@ngrx\/store<\/code> module are tied together. As a result I found a bunch of interesting stuff related to each component of the module and this is what I&rsquo;ll be describing in this article. We\u2019re going to examine each entity in detail and I&rsquo;ll explain its role in the overall architecture.<\/p>\n<p>Before diving in, let\u2019s quickly recap what the main entities are:<\/p>\n<ul>\n<li><strong>State:<\/strong> a data structure where the internal state of the application is kept<\/li>\n<li><strong>Store<\/strong>: a bridge between the data consumer and the state<\/li>\n<li><strong>Actions<\/strong>: a mechanism that triggers state changes<\/li>\n<li><strong>Reducers<\/strong>: a mechanism that performs state changes by writing into state<\/li>\n<li><strong>Meta-reducers<\/strong>: a mechanism to hook into the action -&gt; reducer pipeline<\/li>\n<\/ul>\n<p>We&rsquo;ll start with actions.<\/p>\n<h2 id=\"actions\">\n  <span>\n  Actions\n  <\/span>\n  <a href=\"#actions\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><p>Actions can be thought of as instructions for reducers and they also represent the base of an effect. They are usually dispatched from the view layer (a smart component, a service etc.) or from effects.<\/p>\n<h3 id=\"creating-actions\">\n  <span>\n  Creating actions\n  <\/span>\n  <a href=\"#creating-actions\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h3><p>Actions can be created in 3 ways:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">action<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">createAction<\/span>(<span style=\"color:#e6db74\">&#39;[Entity] simple action&#39;<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">action<\/span>();\n<\/span><\/span><\/code><\/pre><\/div><div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">action<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">createAction<\/span>(<span style=\"color:#e6db74\">&#39;[Entity] simple action&#39;<\/span>, <span style=\"color:#a6e22e\">props<\/span><span style=\"color:#f92672\">&lt;<\/span>{ <span style=\"color:#a6e22e\">name<\/span>: <span style=\"color:#66d9ef\">string<\/span>, <span style=\"color:#a6e22e\">age<\/span>: <span style=\"color:#66d9ef\">number<\/span>, }<span style=\"color:#f92672\">&gt;<\/span>());\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">action<\/span>({ <span style=\"color:#a6e22e\">name<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;andrei&#39;<\/span>, <span style=\"color:#a6e22e\">age<\/span>: <span style=\"color:#66d9ef\">18<\/span> });\n<\/span><\/span><\/code><\/pre><\/div><div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">action<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">createAction<\/span>(<span style=\"color:#e6db74\">&#39;action&#39;<\/span>,(<span style=\"color:#a6e22e\">u<\/span>: <span style=\"color:#66d9ef\">User<\/span>, <span style=\"color:#a6e22e\">prefix<\/span>: <span style=\"color:#66d9ef\">string<\/span>) <span style=\"color:#f92672\">=&gt;<\/span> ({ <span style=\"color:#a6e22e\">name<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">`<\/span><span style=\"color:#e6db74\">${<\/span><span style=\"color:#a6e22e\">prefix<\/span><span style=\"color:#e6db74\">}${<\/span><span style=\"color:#a6e22e\">u<\/span>.<span style=\"color:#a6e22e\">name<\/span><span style=\"color:#e6db74\">}<\/span><span style=\"color:#e6db74\">`<\/span> }) );\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">u<\/span>: <span style=\"color:#66d9ef\">User<\/span> <span style=\"color:#f92672\">=<\/span> { <span style=\"color:#75715e\">\/* ... *\/<\/span> };\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">action<\/span>(<span style=\"color:#a6e22e\">u<\/span>, <span style=\"color:#e6db74\">&#39;@@@@&#39;<\/span>);\n<\/span><\/span><\/code><\/pre><\/div><p>In each case, the return value of the function will be an object that will contain at least this property: <code>{ type: T }<\/code>.<\/p>\n<p>Also, the type (first argument of <code>createAction<\/code>) will be attached as property to the function. This is useful to know when reducers are created.<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">function<\/span> <span style=\"color:#a6e22e\">defineType<\/span>&lt;<span style=\"color:#f92672\">T<\/span> <span style=\"color:#a6e22e\">extends<\/span> <span style=\"color:#a6e22e\">string<\/span>&gt;(\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">type<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#a6e22e\">T<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">creator<\/span>: <span style=\"color:#66d9ef\">Creator<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>)<span style=\"color:#f92672\">:<\/span> <span style=\"color:#a6e22e\">ActionCreator<\/span>&lt;<span style=\"color:#f92672\">T<\/span>&gt; {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">return<\/span> Object.<span style=\"color:#a6e22e\">defineProperty<\/span>(<span style=\"color:#a6e22e\">creator<\/span>, <span style=\"color:#e6db74\">&#39;type&#39;<\/span>, {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">value<\/span>: <span style=\"color:#66d9ef\">type<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">writable<\/span>: <span style=\"color:#66d9ef\">false<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  });\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><h3 id=\"typescripts-magic\">\n  <span>\n  TypeScript\u2019s magic\n  <\/span>\n  <a href=\"#typescripts-magic\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h3><p>Now are going to reveal what important role TypeScript plays here. Ever wondered, for example, why is the <code>props()<\/code> function useful? Let&rsquo;s find out!<\/p>\n<p>The <code>createAction<\/code> function comes with 3 overloads:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">export<\/span> <span style=\"color:#66d9ef\">declare<\/span> <span style=\"color:#66d9ef\">interface<\/span> <span style=\"color:#a6e22e\">TypedAction<\/span>&lt;<span style=\"color:#f92672\">T<\/span> <span style=\"color:#a6e22e\">extends<\/span> <span style=\"color:#a6e22e\">string<\/span>&gt; <span style=\"color:#66d9ef\">extends<\/span> <span style=\"color:#a6e22e\">Action<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">readonly<\/span> <span style=\"color:#66d9ef\">type<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#a6e22e\">T<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">export<\/span> <span style=\"color:#66d9ef\">type<\/span> <span style=\"color:#a6e22e\">ActionCreator<\/span><span style=\"color:#f92672\">&lt;<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">T<\/span> <span style=\"color:#66d9ef\">extends<\/span> <span style=\"color:#66d9ef\">string<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">string<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">C<\/span> <span style=\"color:#66d9ef\">extends<\/span> <span style=\"color:#a6e22e\">Creator<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">Creator<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#f92672\">&gt;<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">C<\/span> <span style=\"color:#f92672\">&amp;<\/span> <span style=\"color:#a6e22e\">TypedAction<\/span>&lt;<span style=\"color:#f92672\">T<\/span>&gt;;\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">export<\/span> <span style=\"color:#66d9ef\">function<\/span> <span style=\"color:#a6e22e\">createAction<\/span>&lt;<span style=\"color:#f92672\">T<\/span> <span style=\"color:#a6e22e\">extends<\/span> <span style=\"color:#a6e22e\">string<\/span>&gt;(\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">type<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#a6e22e\">T<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>)<span style=\"color:#f92672\">:<\/span> <span style=\"color:#a6e22e\">ActionCreator<\/span>&lt;<span style=\"color:#f92672\">T<\/span><span style=\"color:#960050;background-color:#1e0010\">,<\/span> <span style=\"color:#960050;background-color:#1e0010\">()<\/span> <span style=\"color:#960050;background-color:#1e0010\">=<\/span>&gt; <span style=\"color:#a6e22e\">TypedAction<\/span>&lt;<span style=\"color:#f92672\">T<\/span>&gt;<span style=\"color:#f92672\">&gt;<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">export<\/span> <span style=\"color:#66d9ef\">function<\/span> <span style=\"color:#a6e22e\">createAction<\/span>&lt;<span style=\"color:#f92672\">T<\/span> <span style=\"color:#a6e22e\">extends<\/span> <span style=\"color:#a6e22e\">string<\/span><span style=\"color:#960050;background-color:#1e0010\">,<\/span> <span style=\"color:#a6e22e\">P<\/span> <span style=\"color:#a6e22e\">extends<\/span> <span style=\"color:#a6e22e\">object<\/span>&gt;(\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">type<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#a6e22e\">T<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">config<\/span>: <span style=\"color:#66d9ef\">Props<\/span>&lt;<span style=\"color:#f92672\">P<\/span>&gt; <span style=\"color:#f92672\">&amp;<\/span> <span style=\"color:#a6e22e\">NotAllowedCheck<\/span>&lt;<span style=\"color:#f92672\">P<\/span>&gt;\n<\/span><\/span><span style=\"display:flex;\"><span>)<span style=\"color:#f92672\">:<\/span> <span style=\"color:#a6e22e\">ActionCreator<\/span>&lt;<span style=\"color:#f92672\">T<\/span><span style=\"color:#960050;background-color:#1e0010\">,<\/span> <span style=\"color:#960050;background-color:#1e0010\">(<\/span><span style=\"color:#a6e22e\">props<\/span><span style=\"color:#960050;background-color:#1e0010\">:<\/span> <span style=\"color:#a6e22e\">P<\/span> <span style=\"color:#960050;background-color:#1e0010\">&amp;<\/span> <span style=\"color:#a6e22e\">NotAllowedCheck<\/span><span style=\"color:#960050;background-color:#1e0010\">&lt;<\/span><span style=\"color:#a6e22e\">P<\/span>&gt;) <span style=\"color:#f92672\">=&gt;<\/span> <span style=\"color:#a6e22e\">P<\/span> <span style=\"color:#f92672\">&amp;<\/span> <span style=\"color:#a6e22e\">TypedAction<\/span>&lt;<span style=\"color:#f92672\">T<\/span>&gt;<span style=\"color:#f92672\">&gt;<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">export<\/span> <span style=\"color:#66d9ef\">function<\/span> <span style=\"color:#a6e22e\">createAction<\/span><span style=\"color:#f92672\">&lt;<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">T<\/span> <span style=\"color:#66d9ef\">extends<\/span> <span style=\"color:#66d9ef\">string<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">P<\/span> <span style=\"color:#66d9ef\">extends<\/span> <span style=\"color:#66d9ef\">any<\/span>[],\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">R<\/span> <span style=\"color:#66d9ef\">extends<\/span> <span style=\"color:#66d9ef\">object<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#f92672\">&gt;<\/span>(\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">type<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#a6e22e\">T<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">creator<\/span>: <span style=\"color:#66d9ef\">Creator<\/span>&lt;<span style=\"color:#f92672\">P<\/span><span style=\"color:#960050;background-color:#1e0010\">,<\/span> <span style=\"color:#a6e22e\">R<\/span>&gt; <span style=\"color:#f92672\">&amp;<\/span> <span style=\"color:#a6e22e\">NotAllowedCheck<\/span>&lt;<span style=\"color:#f92672\">R<\/span>&gt;\n<\/span><\/span><span style=\"display:flex;\"><span>)<span style=\"color:#f92672\">:<\/span> <span style=\"color:#a6e22e\">FunctionWithParametersType<\/span>&lt;<span style=\"color:#f92672\">P<\/span><span style=\"color:#960050;background-color:#1e0010\">,<\/span> <span style=\"color:#a6e22e\">R<\/span> <span style=\"color:#960050;background-color:#1e0010\">&amp;<\/span> <span style=\"color:#a6e22e\">TypedAction<\/span><span style=\"color:#960050;background-color:#1e0010\">&lt;<\/span><span style=\"color:#a6e22e\">T<\/span>&gt;<span style=\"color:#f92672\">&gt;<\/span> <span style=\"color:#f92672\">&amp;<\/span> <span style=\"color:#a6e22e\">TypedAction<\/span>&lt;<span style=\"color:#f92672\">T<\/span>&gt;;\n<\/span><\/span><\/code><\/pre><\/div><p>which implies that the function\u2019s body will have to contain a few type guards in order to get the types right.<\/p>\n<p><code>ActionCreator&lt;T, C&gt;<\/code> represents a function of type <code>C<\/code> that has a readonly property <code>type<\/code> of type <code>T<\/code>. The <code>type<\/code> can also be used to discriminate unions.<\/p>\n<p>Let\u2019s examine each overload.<\/p>\n<h3 id=\"createaction-with-only-type-parameter\">\n  <span>\n  <code>createAction<\/code> with only <code>type<\/code> parameter\n  <\/span>\n  <a href=\"#createaction-with-only-type-parameter\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h3><div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">action<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">createAction<\/span>(<span style=\"color:#e6db74\">&#39;[Entity] simple action&#39;<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">action<\/span>(); <span style=\"color:#75715e\">\/\/ { type: [Entity] simple action }\n<\/span><\/span><\/span><\/code><\/pre><\/div><p>corresponds to this overload:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">export<\/span> <span style=\"color:#66d9ef\">function<\/span> <span style=\"color:#a6e22e\">createAction<\/span>&lt;<span style=\"color:#f92672\">T<\/span> <span style=\"color:#a6e22e\">extends<\/span> <span style=\"color:#a6e22e\">string<\/span>&gt;(\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">type<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#a6e22e\">T<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>)<span style=\"color:#f92672\">:<\/span> <span style=\"color:#a6e22e\">ActionCreator<\/span>&lt;<span style=\"color:#f92672\">T<\/span><span style=\"color:#960050;background-color:#1e0010\">,<\/span> <span style=\"color:#960050;background-color:#1e0010\">()<\/span> <span style=\"color:#960050;background-color:#1e0010\">=<\/span>&gt; <span style=\"color:#a6e22e\">TypedAction<\/span>&lt;<span style=\"color:#f92672\">T<\/span>&gt;<span style=\"color:#f92672\">&gt;<\/span>;\n<\/span><\/span><\/code><\/pre><\/div><p>We can deduce from the above snippet that the return type will be a function which will return an object with a property <code>type<\/code>.<\/p>\n<p>Here\u2019s the type guard which reveals that:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">export<\/span> <span style=\"color:#66d9ef\">function<\/span> <span style=\"color:#a6e22e\">createAction<\/span>&lt;<span style=\"color:#f92672\">T<\/span> <span style=\"color:#a6e22e\">extends<\/span> <span style=\"color:#a6e22e\">string<\/span><span style=\"color:#960050;background-color:#1e0010\">,<\/span> <span style=\"color:#a6e22e\">C<\/span> <span style=\"color:#a6e22e\">extends<\/span> <span style=\"color:#a6e22e\">Creator<\/span>&gt;(\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">type<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#a6e22e\">T<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">config<\/span><span style=\"color:#f92672\">?:<\/span> { <span style=\"color:#a6e22e\">_as<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;props&#39;<\/span> } <span style=\"color:#f92672\">|<\/span> <span style=\"color:#a6e22e\">C<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>)<span style=\"color:#f92672\">:<\/span> <span style=\"color:#a6e22e\">ActionCreator<\/span>&lt;<span style=\"color:#f92672\">T<\/span>&gt; {\n<\/span><\/span><span style=\"display:flex;\"><span>  \n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#66d9ef\">as<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">config<\/span> <span style=\"color:#f92672\">?<\/span> <span style=\"color:#a6e22e\">config<\/span>.<span style=\"color:#a6e22e\">_as<\/span> <span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;empty&#39;<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>  \n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">switch<\/span> (<span style=\"color:#66d9ef\">as<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">case<\/span> <span style=\"color:#e6db74\">&#39;empty&#39;<\/span><span style=\"color:#f92672\">:<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#a6e22e\">defineType<\/span>(<span style=\"color:#66d9ef\">type<\/span>, () <span style=\"color:#f92672\">=&gt;<\/span> ({ <span style=\"color:#66d9ef\">type<\/span> }));\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#75715e\">\/* ... *\/<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>  }\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p>where <code>defineType<\/code> will attach the property <code>type<\/code> to the function(in this case <code>() =&gt; ({ type })<\/code>).<\/p>\n<h3 id=\"createaction-with-props\">\n  <span>\n  <code>createAction<\/code> with props\n  <\/span>\n  <a href=\"#createaction-with-props\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h3><p>This approach can be used when you want to dispatch an action that contains some data which is valuable to the reducer(e.g <code>userActions.add({ name, age })<\/code>).<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">action<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">createAction<\/span>(<span style=\"color:#e6db74\">&#39;[Entity] simple action&#39;<\/span>, <span style=\"color:#a6e22e\">props<\/span><span style=\"color:#f92672\">&lt;<\/span>{ <span style=\"color:#a6e22e\">name<\/span>: <span style=\"color:#66d9ef\">string<\/span>, <span style=\"color:#a6e22e\">age<\/span>: <span style=\"color:#66d9ef\">number<\/span>, }<span style=\"color:#f92672\">&gt;<\/span>());\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">action<\/span>({ <span style=\"color:#a6e22e\">name<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;andrei&#39;<\/span>, <span style=\"color:#a6e22e\">age<\/span>: <span style=\"color:#66d9ef\">18<\/span> });\n<\/span><\/span><\/code><\/pre><\/div><p>What <code>props&lt;T&gt;()<\/code> does is to return an object with a predefined key(<code>_as: 'props'<\/code>) and with a key of type <code>T<\/code> which is useful for type inference.<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">export<\/span> <span style=\"color:#66d9ef\">function<\/span> <span style=\"color:#a6e22e\">props<\/span>&lt;<span style=\"color:#f92672\">P<\/span> <span style=\"color:#a6e22e\">extends<\/span> <span style=\"color:#a6e22e\">object<\/span>&gt;()<span style=\"color:#f92672\">:<\/span> <span style=\"color:#a6e22e\">Props<\/span>&lt;<span style=\"color:#f92672\">P<\/span>&gt; {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">return<\/span> { <span style=\"color:#a6e22e\">_as<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;props&#39;<\/span>, <span style=\"color:#a6e22e\">_p<\/span>: <span style=\"color:#66d9ef\">undefined<\/span><span style=\"color:#f92672\">!<\/span> };\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">export<\/span> <span style=\"color:#66d9ef\">interface<\/span> <span style=\"color:#a6e22e\">Props<\/span>&lt;<span style=\"color:#f92672\">T<\/span>&gt; {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">_as<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;props&#39;<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">_p<\/span>: <span style=\"color:#66d9ef\">T<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p>This is how the overload looks:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">export<\/span> <span style=\"color:#66d9ef\">function<\/span> <span style=\"color:#a6e22e\">createAction<\/span>&lt;<span style=\"color:#f92672\">T<\/span> <span style=\"color:#a6e22e\">extends<\/span> <span style=\"color:#a6e22e\">string<\/span><span style=\"color:#960050;background-color:#1e0010\">,<\/span> <span style=\"color:#a6e22e\">P<\/span> <span style=\"color:#a6e22e\">extends<\/span> <span style=\"color:#a6e22e\">object<\/span>&gt;(\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">type<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#a6e22e\">T<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">config<\/span>: <span style=\"color:#66d9ef\">Props<\/span>&lt;<span style=\"color:#f92672\">P<\/span>&gt; <span style=\"color:#f92672\">&amp;<\/span> <span style=\"color:#a6e22e\">NotAllowedCheck<\/span>&lt;<span style=\"color:#f92672\">P<\/span>&gt;\n<\/span><\/span><span style=\"display:flex;\"><span>)<span style=\"color:#f92672\">:<\/span> <span style=\"color:#a6e22e\">ActionCreator<\/span>&lt;<span style=\"color:#f92672\">T<\/span><span style=\"color:#960050;background-color:#1e0010\">,<\/span> <span style=\"color:#960050;background-color:#1e0010\">(<\/span><span style=\"color:#a6e22e\">props<\/span><span style=\"color:#960050;background-color:#1e0010\">:<\/span> <span style=\"color:#a6e22e\">P<\/span> <span style=\"color:#960050;background-color:#1e0010\">&amp;<\/span> <span style=\"color:#a6e22e\">NotAllowedCheck<\/span><span style=\"color:#960050;background-color:#1e0010\">&lt;<\/span><span style=\"color:#a6e22e\">P<\/span>&gt;) <span style=\"color:#f92672\">=&gt;<\/span> <span style=\"color:#a6e22e\">P<\/span> <span style=\"color:#f92672\">&amp;<\/span> <span style=\"color:#a6e22e\">TypedAction<\/span>&lt;<span style=\"color:#f92672\">T<\/span>&gt;<span style=\"color:#f92672\">&gt;<\/span>;\n<\/span><\/span><\/code><\/pre><\/div><p><code>config<\/code> will be an instance of <code>props&lt;P&gt;()<\/code>, which allows <code>P<\/code> to be inferred and to be used in <code>(props: P &amp; NotAllowedCheck&lt;P&gt;) =&gt; P &amp; TypedAction&lt;T&gt;&gt;<\/code>.<\/p>\n<p><code>ActionCreator&lt;T, (props: P &amp; NotAllowedCheck&lt;P&gt;) =&gt; P &amp; TypedAction&lt;T&gt;&gt;<\/code> will be a function that can be called with one argument(an object), whose type will be <code>P<\/code>(inferred from <code>props&lt;P&gt;()<\/code>) and whose return type will be an object that contains all the properties of <code>P<\/code>(<code>P<\/code> is an object) and the <code>type<\/code> property(<code>TypedAction&lt;T&gt;<\/code>).<\/p>\n<p>Here\u2019s how <code>createAction<\/code> establishes this:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">export<\/span> <span style=\"color:#66d9ef\">function<\/span> <span style=\"color:#a6e22e\">createAction<\/span>&lt;<span style=\"color:#f92672\">T<\/span> <span style=\"color:#a6e22e\">extends<\/span> <span style=\"color:#a6e22e\">string<\/span><span style=\"color:#960050;background-color:#1e0010\">,<\/span> <span style=\"color:#a6e22e\">C<\/span> <span style=\"color:#a6e22e\">extends<\/span> <span style=\"color:#a6e22e\">Creator<\/span>&gt;(\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">type<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#a6e22e\">T<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">config<\/span><span style=\"color:#f92672\">?:<\/span> { <span style=\"color:#a6e22e\">_as<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;props&#39;<\/span> } <span style=\"color:#f92672\">|<\/span> <span style=\"color:#a6e22e\">C<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>)<span style=\"color:#f92672\">:<\/span> <span style=\"color:#a6e22e\">ActionCreator<\/span>&lt;<span style=\"color:#f92672\">T<\/span>&gt; {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#66d9ef\">typeof<\/span> <span style=\"color:#a6e22e\">config<\/span> <span style=\"color:#f92672\">===<\/span> <span style=\"color:#e6db74\">&#39;function&#39;<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#75715e\">\/* ... *\/<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#75715e\">\/\/ `config._as` - returned from `props()`\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>  <span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#66d9ef\">as<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">config<\/span> <span style=\"color:#f92672\">?<\/span> <span style=\"color:#a6e22e\">config<\/span>.<span style=\"color:#a6e22e\">_as<\/span> <span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;empty&#39;<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>  \n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">switch<\/span> (<span style=\"color:#66d9ef\">as<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#75715e\">\/* ... *\/<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">case<\/span> <span style=\"color:#e6db74\">&#39;props&#39;<\/span><span style=\"color:#f92672\">:<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#a6e22e\">defineType<\/span>(<span style=\"color:#66d9ef\">type<\/span>, (<span style=\"color:#a6e22e\">props<\/span>: <span style=\"color:#66d9ef\">object<\/span>) <span style=\"color:#f92672\">=&gt;<\/span> ({\n<\/span><\/span><span style=\"display:flex;\"><span>        ...<span style=\"color:#a6e22e\">props<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#66d9ef\">type<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>      }));\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#75715e\">\/* ... *\/<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>  }\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><h3 id=\"createaction-with-a-function\">\n  <span>\n  <code>createAction<\/code> with a function\n  <\/span>\n  <a href=\"#createaction-with-a-function\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h3><p>This comes in handy when you want to modify the data before it reaches the reducer. Or you might simply want to determine the action\u2019s data based on some more complicated logic.<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">action<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">createAction<\/span>(\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#e6db74\">&#39;action&#39;<\/span>, \n<\/span><\/span><span style=\"display:flex;\"><span>  (<span style=\"color:#a6e22e\">u<\/span>: <span style=\"color:#66d9ef\">User<\/span>, <span style=\"color:#a6e22e\">prefix<\/span>: <span style=\"color:#66d9ef\">string<\/span>) <span style=\"color:#f92672\">=&gt;<\/span> ({ <span style=\"color:#a6e22e\">name<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">`<\/span><span style=\"color:#e6db74\">${<\/span><span style=\"color:#a6e22e\">prefix<\/span><span style=\"color:#e6db74\">}${<\/span><span style=\"color:#a6e22e\">u<\/span>.<span style=\"color:#a6e22e\">name<\/span><span style=\"color:#e6db74\">}<\/span><span style=\"color:#e6db74\">`<\/span> }) \n<\/span><\/span><span style=\"display:flex;\"><span>);\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">u<\/span>: <span style=\"color:#66d9ef\">User<\/span> <span style=\"color:#f92672\">=<\/span> { <span style=\"color:#75715e\">\/* ... *\/<\/span> };\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">action<\/span>(<span style=\"color:#a6e22e\">u<\/span>, <span style=\"color:#e6db74\">&#39;@@@@&#39;<\/span>);\n<\/span><\/span><\/code><\/pre><\/div><p>The overload for this looks as follows:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">export<\/span> <span style=\"color:#66d9ef\">function<\/span> <span style=\"color:#a6e22e\">createAction<\/span><span style=\"color:#f92672\">&lt;<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">T<\/span> <span style=\"color:#66d9ef\">extends<\/span> <span style=\"color:#66d9ef\">string<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">P<\/span> <span style=\"color:#66d9ef\">extends<\/span> <span style=\"color:#66d9ef\">any<\/span>[],\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">R<\/span> <span style=\"color:#66d9ef\">extends<\/span> <span style=\"color:#66d9ef\">object<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#f92672\">&gt;<\/span>(\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">type<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#a6e22e\">T<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">creator<\/span>: <span style=\"color:#66d9ef\">Creator<\/span>&lt;<span style=\"color:#f92672\">P<\/span><span style=\"color:#960050;background-color:#1e0010\">,<\/span> <span style=\"color:#a6e22e\">R<\/span>&gt; <span style=\"color:#f92672\">&amp;<\/span> <span style=\"color:#a6e22e\">NotAllowedCheck<\/span>&lt;<span style=\"color:#f92672\">R<\/span>&gt;\n<\/span><\/span><span style=\"display:flex;\"><span>)<span style=\"color:#f92672\">:<\/span> <span style=\"color:#a6e22e\">FunctionWithParametersType<\/span>&lt;<span style=\"color:#f92672\">P<\/span><span style=\"color:#960050;background-color:#1e0010\">,<\/span> <span style=\"color:#a6e22e\">R<\/span> <span style=\"color:#960050;background-color:#1e0010\">&amp;<\/span> <span style=\"color:#a6e22e\">TypedAction<\/span><span style=\"color:#960050;background-color:#1e0010\">&lt;<\/span><span style=\"color:#a6e22e\">T<\/span>&gt;<span style=\"color:#f92672\">&gt;<\/span> <span style=\"color:#f92672\">&amp;<\/span> <span style=\"color:#a6e22e\">TypedAction<\/span>&lt;<span style=\"color:#f92672\">T<\/span>&gt;;\n<\/span><\/span><\/code><\/pre><\/div><p><code>Creator&lt;P, R&gt;<\/code> is simply a function takes up a parameter of type <code>P<\/code> and returns an object of type <code>R<\/code>. This will allow us to infer the <code>P<\/code> and <code>R<\/code> types. <code>NotAllowedCheck&lt;R&gt;<\/code> makes sure that the <code>creator<\/code> is not an existing action or an array. It must be a function that receives some arguments and based on them, it returns an object that represents the action&rsquo;s data.<\/p>\n<p><code>FunctionWithParametersType&lt;P, R &amp; TypedAction&lt;T&gt;&gt; &amp; TypedAction&lt;T&gt;;<\/code> means that the return type must be a function whose arguments are of type <code>P<\/code>(inferred from <code>Creator&lt;P, R&gt;<\/code>), which returns an object of type <code>R<\/code>(also inferred from <code>Creator&lt;P, R&gt;<\/code>) and has a property <code>type<\/code>.<\/p>\n<p>This is what happens inside <code>createAction<\/code>:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">export<\/span> <span style=\"color:#66d9ef\">function<\/span> <span style=\"color:#a6e22e\">createAction<\/span>&lt;<span style=\"color:#f92672\">T<\/span> <span style=\"color:#a6e22e\">extends<\/span> <span style=\"color:#a6e22e\">string<\/span><span style=\"color:#960050;background-color:#1e0010\">,<\/span> <span style=\"color:#a6e22e\">C<\/span> <span style=\"color:#a6e22e\">extends<\/span> <span style=\"color:#a6e22e\">Creator<\/span>&gt;(\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">type<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#a6e22e\">T<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">config<\/span><span style=\"color:#f92672\">?:<\/span> { <span style=\"color:#a6e22e\">_as<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;props&#39;<\/span> } <span style=\"color:#f92672\">|<\/span> <span style=\"color:#a6e22e\">C<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>)<span style=\"color:#f92672\">:<\/span> <span style=\"color:#a6e22e\">ActionCreator<\/span>&lt;<span style=\"color:#f92672\">T<\/span>&gt; {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#66d9ef\">typeof<\/span> <span style=\"color:#a6e22e\">config<\/span> <span style=\"color:#f92672\">===<\/span> <span style=\"color:#e6db74\">&#39;function&#39;<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#a6e22e\">defineType<\/span>(<span style=\"color:#66d9ef\">type<\/span>, (...<span style=\"color:#a6e22e\">args<\/span>: <span style=\"color:#66d9ef\">any<\/span>[]) <span style=\"color:#f92672\">=&gt;<\/span> ({\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#75715e\">\/\/ `config(...args)` will return an object\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>      ...<span style=\"color:#a6e22e\">config<\/span>(...<span style=\"color:#a6e22e\">args<\/span>),\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#66d9ef\">type<\/span>, <span style=\"color:#75715e\">\/\/ The `type` property is always returned\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>    }));\n<\/span><\/span><span style=\"display:flex;\"><span>  }\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#75715e\">\/* ... *\/<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><h2 id=\"reducers\">\n  <span>\n  Reducers\n  <\/span>\n  <a href=\"#reducers\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><p>Reducers are pure functions that are responsible for state changes.<\/p>\n<p>Here\u2019s the interface that describes the shape of a reducer:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">export<\/span> <span style=\"color:#66d9ef\">interface<\/span> <span style=\"color:#a6e22e\">ActionReducer<\/span>&lt;<span style=\"color:#f92672\">T<\/span><span style=\"color:#960050;background-color:#1e0010\">,<\/span> <span style=\"color:#a6e22e\">V<\/span> <span style=\"color:#a6e22e\">extends<\/span> <span style=\"color:#a6e22e\">Action <\/span><span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">Action<\/span>&gt; {\n<\/span><\/span><span style=\"display:flex;\"><span>  (<span style=\"color:#a6e22e\">state<\/span>: <span style=\"color:#66d9ef\">T<\/span> <span style=\"color:#f92672\">|<\/span> <span style=\"color:#66d9ef\">undefined<\/span>, <span style=\"color:#a6e22e\">action<\/span>: <span style=\"color:#66d9ef\">V<\/span>)<span style=\"color:#f92672\">:<\/span> <span style=\"color:#a6e22e\">T<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p>As you can see, a reducer takes 2 parameters: the current <code>state<\/code> and the current <code>action<\/code> that has been dispatched.<\/p>\n<h3 id=\"providing-reducers\">\n  <span>\n  Providing reducers\n  <\/span>\n  <a href=\"#providing-reducers\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h3><p>Reducers can be provided in two ways:<\/p>\n<ul>\n<li>\n<p>an object whose values are reducers created with the help of <code>createReducer<\/code><\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">StoreModule<\/span>.<span style=\"color:#a6e22e\">forRoot<\/span>({ <span style=\"color:#a6e22e\">foo<\/span>: <span style=\"color:#66d9ef\">fooReducer<\/span>, <span style=\"color:#a6e22e\">user<\/span>: <span style=\"color:#66d9ef\">UserReducer<\/span> })\n<\/span><\/span><\/code><\/pre><\/div><p>Each key represents a slice of the store.<\/p>\n<\/li>\n<li>\n<p>an injection token<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">REDUCERS_TOKEN<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">new<\/span> <span style=\"color:#a6e22e\">InjectionToken<\/span>(<span style=\"color:#e6db74\">&#39;REDUCERS&#39;<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">@NgModule<\/span>({\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">imports<\/span><span style=\"color:#f92672\">:<\/span> [\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">StoreModule<\/span>.<span style=\"color:#a6e22e\">forRoot<\/span>(<span style=\"color:#a6e22e\">REDUCERS_TOKEN<\/span>)\n<\/span><\/span><span style=\"display:flex;\"><span>  ],\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">providers<\/span><span style=\"color:#f92672\">:<\/span> [\n<\/span><\/span><span style=\"display:flex;\"><span>    { <span style=\"color:#a6e22e\">provide<\/span>: <span style=\"color:#66d9ef\">REDUCERS_TOKEN<\/span>, <span style=\"color:#a6e22e\">useValue<\/span><span style=\"color:#f92672\">:<\/span> { <span style=\"color:#a6e22e\">foo<\/span>: <span style=\"color:#66d9ef\">fooReducer<\/span> } }\n<\/span><\/span><span style=\"display:flex;\"><span>  ],\n<\/span><\/span><span style=\"display:flex;\"><span>}) <span style=\"color:#75715e\">\/* ... *\/<\/span>\n<\/span><\/span><\/code><\/pre><\/div><\/li>\n<\/ul>\n<h3 id=\"how-are-reducers-set-up\">\n  <span>\n  How are reducers set up?\n  <\/span>\n  <a href=\"#how-are-reducers-set-up\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h3><p>Let\u2019s assume reducers are provided this way:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">StoreModule<\/span>.<span style=\"color:#a6e22e\">forRoot<\/span>({ <span style=\"color:#a6e22e\">entity<\/span>: <span style=\"color:#66d9ef\">entityReducer<\/span> })\n<\/span><\/span><\/code><\/pre><\/div><p><code>StoreModule.forRoot<\/code> will return a <code>ModuleWithProviders<\/code> object which contains, among others, these providers:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/* ... *\/<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>{\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">provide<\/span>: <span style=\"color:#66d9ef\">_REDUCER_FACTORY<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">useValue<\/span>: <span style=\"color:#66d9ef\">config.reducerFactory<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#f92672\">?<\/span> <span style=\"color:#a6e22e\">config.reducerFactory<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>    : <span style=\"color:#66d9ef\">combineReducers<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>},\n<\/span><\/span><span style=\"display:flex;\"><span>{\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">provide<\/span>: <span style=\"color:#66d9ef\">REDUCER_FACTORY<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">deps<\/span><span style=\"color:#f92672\">:<\/span> [<span style=\"color:#a6e22e\">_REDUCER_FACTORY<\/span>, <span style=\"color:#a6e22e\">_RESOLVED_META_REDUCERS<\/span>],\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">useFactory<\/span>: <span style=\"color:#66d9ef\">createReducerFactory<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>},\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/* ... *\/<\/span>\n<\/span><\/span><\/code><\/pre><\/div><p>As you can see, unless you provide a custom reducer factory, the <code>combineReducers<\/code> function will be used instead(we&rsquo;ll have a look at it in a moment). <code>createReducerFactory<\/code> is mainly used to add the <strong>meta-reducers<\/strong>.<\/p>\n<p>The <code>REDUCER_FACTORY<\/code> token will only be injected in <code>ReducerManager<\/code> class:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">export<\/span> <span style=\"color:#66d9ef\">class<\/span> <span style=\"color:#a6e22e\">ReducerManager<\/span> <span style=\"color:#75715e\">\/* ... *\/<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">constructor<\/span>(\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">@Inject<\/span>(<span style=\"color:#a6e22e\">INITIAL_STATE<\/span>) <span style=\"color:#66d9ef\">private<\/span> <span style=\"color:#a6e22e\">initialState<\/span>: <span style=\"color:#66d9ef\">any<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">@Inject<\/span>(<span style=\"color:#a6e22e\">INITIAL_REDUCERS<\/span>) <span style=\"color:#66d9ef\">private<\/span> <span style=\"color:#a6e22e\">reducers<\/span>: <span style=\"color:#66d9ef\">ActionReducerMap<\/span>&lt;<span style=\"color:#f92672\">any<\/span><span style=\"color:#960050;background-color:#1e0010\">,<\/span> <span style=\"color:#a6e22e\">any<\/span>&gt;,\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">@Inject<\/span>(<span style=\"color:#a6e22e\">REDUCER_FACTORY<\/span>)\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">private<\/span> <span style=\"color:#a6e22e\">reducerFactory<\/span>: <span style=\"color:#66d9ef\">ActionReducerFactory<\/span>&lt;<span style=\"color:#f92672\">any<\/span><span style=\"color:#960050;background-color:#1e0010\">,<\/span> <span style=\"color:#a6e22e\">any<\/span>&gt;\n<\/span><\/span><span style=\"display:flex;\"><span>  ) {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">super<\/span>(<span style=\"color:#a6e22e\">reducerFactory<\/span>(<span style=\"color:#a6e22e\">reducers<\/span>, <span style=\"color:#a6e22e\">initialState<\/span>));\n<\/span><\/span><span style=\"display:flex;\"><span>  }\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#75715e\">\/* ... *\/<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p>As soon as that happens, the <code>createReducerFactory<\/code> function will be invoked, meaning that <code>reducerFactory<\/code> property will hold its return value, which is a function that takes an object of reducers(the <code>reducers<\/code> parameter below) and, optionally, the <code>initialState<\/code>:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">export<\/span> <span style=\"color:#66d9ef\">function<\/span> <span style=\"color:#a6e22e\">createReducerFactory<\/span>&lt;<span style=\"color:#f92672\">T<\/span><span style=\"color:#960050;background-color:#1e0010\">,<\/span> <span style=\"color:#a6e22e\">V<\/span> <span style=\"color:#a6e22e\">extends<\/span> <span style=\"color:#a6e22e\">Action <\/span><span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">Action<\/span>&gt;(\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">reducerFactory<\/span>: <span style=\"color:#66d9ef\">ActionReducerFactory<\/span>&lt;<span style=\"color:#f92672\">T<\/span><span style=\"color:#960050;background-color:#1e0010\">,<\/span> <span style=\"color:#a6e22e\">V<\/span>&gt;,\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">metaReducers?<\/span>: <span style=\"color:#66d9ef\">MetaReducer<\/span>&lt;<span style=\"color:#f92672\">T<\/span><span style=\"color:#960050;background-color:#1e0010\">,<\/span> <span style=\"color:#a6e22e\">V<\/span>&gt;[]\n<\/span><\/span><span style=\"display:flex;\"><span>)<span style=\"color:#f92672\">:<\/span> <span style=\"color:#a6e22e\">ActionReducerFactory<\/span>&lt;<span style=\"color:#f92672\">T<\/span><span style=\"color:#960050;background-color:#1e0010\">,<\/span> <span style=\"color:#a6e22e\">V<\/span>&gt; {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">if<\/span> (Array.<span style=\"color:#a6e22e\">isArray<\/span>(<span style=\"color:#a6e22e\">metaReducers<\/span>) <span style=\"color:#f92672\">&amp;&amp;<\/span> <span style=\"color:#a6e22e\">metaReducers<\/span>.<span style=\"color:#a6e22e\">length<\/span> <span style=\"color:#f92672\">&gt;<\/span> <span style=\"color:#ae81ff\">0<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>    (<span style=\"color:#a6e22e\">reducerFactory<\/span> <span style=\"color:#66d9ef\">as<\/span> <span style=\"color:#66d9ef\">any<\/span>) <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">compose<\/span>.<span style=\"color:#a6e22e\">apply<\/span>(<span style=\"color:#66d9ef\">null<\/span>, [\n<\/span><\/span><span style=\"display:flex;\"><span>      ...<span style=\"color:#a6e22e\">metaReducers<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#a6e22e\">reducerFactory<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>    ]);\n<\/span><\/span><span style=\"display:flex;\"><span>  }\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#75715e\">\/\/ `ReducerManager.reducerFactory` will hold this function! - it is immediately invoked in the constructor\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>  <span style=\"color:#66d9ef\">return<\/span> (<span style=\"color:#a6e22e\">reducers<\/span>: <span style=\"color:#66d9ef\">ActionReducerMap<\/span>&lt;<span style=\"color:#f92672\">T<\/span><span style=\"color:#960050;background-color:#1e0010\">,<\/span> <span style=\"color:#a6e22e\">V<\/span>&gt;, <span style=\"color:#a6e22e\">initialState?<\/span>: <span style=\"color:#66d9ef\">InitialState<\/span>&lt;<span style=\"color:#f92672\">T<\/span>&gt;) <span style=\"color:#f92672\">=&gt;<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">reducer<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">reducerFactory<\/span>(<span style=\"color:#a6e22e\">reducers<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">return<\/span> (<span style=\"color:#a6e22e\">state<\/span>: <span style=\"color:#66d9ef\">T<\/span> <span style=\"color:#f92672\">|<\/span> <span style=\"color:#66d9ef\">undefined<\/span>, <span style=\"color:#a6e22e\">action<\/span>: <span style=\"color:#66d9ef\">V<\/span>) <span style=\"color:#f92672\">=&gt;<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#75715e\">\/\/ This function is the value resulted from `super(reducerFactory(reducers, initialState));`(takes place inside `ReducerManager`&#39;s constructor)\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>      <span style=\"color:#a6e22e\">state<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">state<\/span> <span style=\"color:#f92672\">===<\/span> <span style=\"color:#66d9ef\">undefined<\/span> <span style=\"color:#f92672\">?<\/span> (<span style=\"color:#a6e22e\">initialState<\/span> <span style=\"color:#66d9ef\">as<\/span> <span style=\"color:#a6e22e\">T<\/span>) <span style=\"color:#f92672\">:<\/span> <span style=\"color:#a6e22e\">state<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#a6e22e\">reducer<\/span>(<span style=\"color:#a6e22e\">state<\/span>, <span style=\"color:#a6e22e\">action<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>    };\n<\/span><\/span><span style=\"display:flex;\"><span>  };\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p>Invoking <code>super(reducerFactory(reducers, initialState))<\/code> will combine all the reducers into one object, whose keys represent the store&rsquo;s slices key corresponds to a reducer:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">export<\/span> <span style=\"color:#66d9ef\">function<\/span> <span style=\"color:#a6e22e\">combineReducers<\/span>(\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">reducers<\/span>: <span style=\"color:#66d9ef\">any<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">initialState<\/span>: <span style=\"color:#66d9ef\">any<\/span> <span style=\"color:#f92672\">=<\/span> {}\n<\/span><\/span><span style=\"display:flex;\"><span>)<span style=\"color:#f92672\">:<\/span> <span style=\"color:#a6e22e\">ActionReducer<\/span>&lt;<span style=\"color:#f92672\">any<\/span><span style=\"color:#960050;background-color:#1e0010\">,<\/span> <span style=\"color:#a6e22e\">Action<\/span>&gt; {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">reducerKeys<\/span> <span style=\"color:#f92672\">=<\/span> Object.<span style=\"color:#a6e22e\">keys<\/span>(<span style=\"color:#a6e22e\">reducers<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">finalReducers<\/span>: <span style=\"color:#66d9ef\">any<\/span> <span style=\"color:#f92672\">=<\/span> {};\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">for<\/span> (<span style=\"color:#66d9ef\">let<\/span> <span style=\"color:#a6e22e\">i<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#ae81ff\">0<\/span>; <span style=\"color:#a6e22e\">i<\/span> <span style=\"color:#f92672\">&lt;<\/span> <span style=\"color:#a6e22e\">reducerKeys<\/span>.<span style=\"color:#a6e22e\">length<\/span>; <span style=\"color:#a6e22e\">i<\/span><span style=\"color:#f92672\">++<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">key<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">reducerKeys<\/span>[<span style=\"color:#a6e22e\">i<\/span>];\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#66d9ef\">typeof<\/span> <span style=\"color:#a6e22e\">reducers<\/span>[<span style=\"color:#a6e22e\">key<\/span>] <span style=\"color:#f92672\">===<\/span> <span style=\"color:#e6db74\">&#39;function&#39;<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#a6e22e\">finalReducers<\/span>[<span style=\"color:#a6e22e\">key<\/span>] <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">reducers<\/span>[<span style=\"color:#a6e22e\">key<\/span>];\n<\/span><\/span><span style=\"display:flex;\"><span>    }\n<\/span><\/span><span style=\"display:flex;\"><span>  }\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#75715e\">\/* \n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">  Remember from the previous snippet: `const reducer = reducerFactory(reducers)`\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">  Now, the `reducer` will be the below function.\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">  *\/<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#66d9ef\">function<\/span> <span style=\"color:#a6e22e\">combination<\/span>(<span style=\"color:#a6e22e\">state<\/span>, <span style=\"color:#a6e22e\">action<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">state<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">state<\/span> <span style=\"color:#f92672\">===<\/span> <span style=\"color:#66d9ef\">undefined<\/span> <span style=\"color:#f92672\">?<\/span> <span style=\"color:#a6e22e\">initialState<\/span> : <span style=\"color:#66d9ef\">state<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">let<\/span> <span style=\"color:#a6e22e\">hasChanged<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">false<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">nextState<\/span>: <span style=\"color:#66d9ef\">any<\/span> <span style=\"color:#f92672\">=<\/span> {};\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">for<\/span> (<span style=\"color:#66d9ef\">let<\/span> <span style=\"color:#a6e22e\">i<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#ae81ff\">0<\/span>; <span style=\"color:#a6e22e\">i<\/span> <span style=\"color:#f92672\">&lt;<\/span> <span style=\"color:#a6e22e\">finalReducerKeys<\/span>.<span style=\"color:#a6e22e\">length<\/span>; <span style=\"color:#a6e22e\">i<\/span><span style=\"color:#f92672\">++<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">key<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">finalReducerKeys<\/span>[<span style=\"color:#a6e22e\">i<\/span>];\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">reducer<\/span>: <span style=\"color:#66d9ef\">any<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">finalReducers<\/span>[<span style=\"color:#a6e22e\">key<\/span>];\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">previousStateForKey<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">state<\/span>[<span style=\"color:#a6e22e\">key<\/span>];\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">nextStateForKey<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">reducer<\/span>(<span style=\"color:#a6e22e\">previousStateForKey<\/span>, <span style=\"color:#a6e22e\">action<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#a6e22e\">nextState<\/span>[<span style=\"color:#a6e22e\">key<\/span>] <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">nextStateForKey<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#a6e22e\">hasChanged<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">hasChanged<\/span> <span style=\"color:#f92672\">||<\/span> <span style=\"color:#a6e22e\">nextStateForKey<\/span> <span style=\"color:#f92672\">!==<\/span> <span style=\"color:#a6e22e\">previousStateForKey<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>    }\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#a6e22e\">hasChanged<\/span> <span style=\"color:#f92672\">?<\/span> <span style=\"color:#a6e22e\">nextState<\/span> : <span style=\"color:#66d9ef\">state<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>  };\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p>Additionally, we can see in the above snippet why the stored data must be immutable. If a reducer returned the same reference of an object, but with a property changed, this would not be reflected into the UI as <code>nextStateForKey !== previousStateForKey<\/code> would fail.<\/p>\n<p>The gist resides in this snippet:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/* ... *\/<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ The below function is the result of \n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ `@Inject(REDUCER_FACTORY) private reducerFactory: ActionReducerFactory&lt;any, any&gt;`\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span><span style=\"color:#66d9ef\">return<\/span> (<span style=\"color:#a6e22e\">reducers<\/span>: <span style=\"color:#66d9ef\">ActionReducerMap<\/span>&lt;<span style=\"color:#f92672\">T<\/span><span style=\"color:#960050;background-color:#1e0010\">,<\/span> <span style=\"color:#a6e22e\">V<\/span>&gt;, <span style=\"color:#a6e22e\">initialState?<\/span>: <span style=\"color:#66d9ef\">InitialState<\/span>&lt;<span style=\"color:#f92672\">T<\/span>&gt;) <span style=\"color:#f92672\">=&gt;<\/span> { <span style=\"color:#75715e\">\/\/ #Fn1\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>  <span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">reducer<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">reducerFactory<\/span>(<span style=\"color:#a6e22e\">reducers<\/span>); <span style=\"color:#75715e\">\/\/ &lt;-\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>  <span style=\"color:#66d9ef\">return<\/span> (<span style=\"color:#a6e22e\">state<\/span>: <span style=\"color:#66d9ef\">T<\/span> <span style=\"color:#f92672\">|<\/span> <span style=\"color:#66d9ef\">undefined<\/span>, <span style=\"color:#a6e22e\">action<\/span>: <span style=\"color:#66d9ef\">V<\/span>) <span style=\"color:#f92672\">=&gt;<\/span> { <span style=\"color:#75715e\">\/\/ #Fn2\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>    <span style=\"color:#a6e22e\">state<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">state<\/span> <span style=\"color:#f92672\">===<\/span> <span style=\"color:#66d9ef\">undefined<\/span> <span style=\"color:#f92672\">?<\/span> (<span style=\"color:#a6e22e\">initialState<\/span> <span style=\"color:#66d9ef\">as<\/span> <span style=\"color:#a6e22e\">T<\/span>) <span style=\"color:#f92672\">:<\/span> <span style=\"color:#a6e22e\">state<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#75715e\">\/\/ `reducer` = `combination` function; when called, will iterate over the existing reducers\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>    <span style=\"color:#75715e\">\/\/ and will call them with the current `state` and `action`\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>    <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#a6e22e\">reducer<\/span>(<span style=\"color:#a6e22e\">state<\/span>, <span style=\"color:#a6e22e\">action<\/span>); \n<\/span><\/span><span style=\"display:flex;\"><span>  };\n<\/span><\/span><span style=\"display:flex;\"><span>};\n<\/span><\/span><\/code><\/pre><\/div><p><code>_super(reducerFactory(reducers, initialState))_<\/code> <em>will cause the above<\/em> <code>_reducerFactory_<\/code> <em>to be called, which will eventually combine all the reducers<\/em>.<\/p>\n<p>After <code>reducerFactory<\/code> is called in <code>const reducer = reducerFactory(reducers)<\/code>, the <code>reducer<\/code> will act on behalf of <code>combination<\/code> function. When invoked, it will iterate over the reducers and invoke them with the given <code>state<\/code> and <code>action<\/code>.<\/p>\n<p>The function in which <code>reducer<\/code> is invoked will be called every time an action is dispatched, meaning that the reducers will be combined(on <code>Fn1<\/code> call) once. Of course, if other reducers are added\/removed later, the reducer object will be re-created properly(<code>Fn1<\/code> called again).<\/p>\n<h3 id=\"createreducer-helper\">\n  <span>\n  createReducer helper\n  <\/span>\n  <a href=\"#createreducer-helper\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h3><p>In order to create reducers that will handle state changes, we can use the <code>createReducer()<\/code> function.<\/p>\n<p>It receives these arguments: the <code>initialState<\/code> and an indefinite number of <code>on<\/code> functions whose type will depend on the type of <code>initialState<\/code>.<\/p>\n<p><strong>The <code>on<\/code> functions are an alternative for using the <code>switch<\/code> statement.<\/strong> An <code>on<\/code> function can receive multiple action creators(results of <a href=\"https:\/\/github.com\/Andrei0872\/my-dev-notes\/blob\/master\/articles\/ngrx\/ngrx-store.md#creating-actions\" target=\"_blank\" rel=\"noopener\"><code>createAction<\/code><\/a>) and the actual reducer as the last argument.<\/p>\n<p>It will return an object <code>{ types: string[], reducer: ActionReducer&lt;S&gt; }<\/code>, where <code>types<\/code> is the type of each provided action creator and reducer is a pure function which handles state changes based on the action and has this signature: <code>(state: T | undefined, action: V): T;<\/code>.<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">export<\/span> <span style=\"color:#66d9ef\">interface<\/span> <span style=\"color:#a6e22e\">On<\/span>&lt;<span style=\"color:#f92672\">S<\/span>&gt; {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">reducer<\/span>: <span style=\"color:#66d9ef\">ActionReducer<\/span>&lt;<span style=\"color:#f92672\">S<\/span>&gt;;\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">types<\/span>: <span style=\"color:#66d9ef\">string<\/span>[];\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">export<\/span> <span style=\"color:#66d9ef\">interface<\/span> <span style=\"color:#a6e22e\">OnReducer<\/span>&lt;<span style=\"color:#f92672\">S<\/span><span style=\"color:#960050;background-color:#1e0010\">,<\/span> <span style=\"color:#a6e22e\">C<\/span> <span style=\"color:#a6e22e\">extends<\/span> <span style=\"color:#a6e22e\">ActionCreator<\/span><span style=\"color:#960050;background-color:#1e0010\">[]<\/span>&gt; {\n<\/span><\/span><span style=\"display:flex;\"><span>  (<span style=\"color:#a6e22e\">state<\/span>: <span style=\"color:#66d9ef\">S<\/span>, <span style=\"color:#a6e22e\">action<\/span>: <span style=\"color:#66d9ef\">ActionType<\/span>&lt;<span style=\"color:#f92672\">C<\/span><span style=\"color:#960050;background-color:#1e0010\">[<\/span><span style=\"color:#a6e22e\">number<\/span><span style=\"color:#960050;background-color:#1e0010\">]<\/span>&gt;)<span style=\"color:#f92672\">:<\/span> <span style=\"color:#a6e22e\">S<\/span>; <span style=\"color:#75715e\">\/\/ `ActionType` - Will infer the type of the action\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>}\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">export<\/span> <span style=\"color:#66d9ef\">function<\/span> <span style=\"color:#a6e22e\">on<\/span>&lt;<span style=\"color:#f92672\">C1<\/span> <span style=\"color:#a6e22e\">extends<\/span> <span style=\"color:#a6e22e\">ActionCreator<\/span><span style=\"color:#960050;background-color:#1e0010\">,<\/span> <span style=\"color:#a6e22e\">S<\/span>&gt;(\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">creator1<\/span>: <span style=\"color:#66d9ef\">C1<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">reducer<\/span>: <span style=\"color:#66d9ef\">OnReducer<\/span>&lt;<span style=\"color:#f92672\">S<\/span><span style=\"color:#960050;background-color:#1e0010\">,<\/span> <span style=\"color:#960050;background-color:#1e0010\">[<\/span><span style=\"color:#a6e22e\">C1<\/span><span style=\"color:#960050;background-color:#1e0010\">]<\/span>&gt;\n<\/span><\/span><span style=\"display:flex;\"><span>)<span style=\"color:#f92672\">:<\/span> <span style=\"color:#a6e22e\">On<\/span>&lt;<span style=\"color:#f92672\">S<\/span>&gt;;\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/* ... Overloads ... *\/<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">export<\/span> <span style=\"color:#66d9ef\">function<\/span> <span style=\"color:#a6e22e\">on<\/span>(\n<\/span><\/span><span style=\"display:flex;\"><span>  ...<span style=\"color:#a6e22e\">args<\/span><span style=\"color:#f92672\">:<\/span> (<span style=\"color:#a6e22e\">ActionCreator<\/span> <span style=\"color:#f92672\">|<\/span> Function)[]\n<\/span><\/span><span style=\"display:flex;\"><span>)<span style=\"color:#f92672\">:<\/span> { <span style=\"color:#a6e22e\">reducer<\/span>: <span style=\"color:#66d9ef\">Function<\/span>; <span style=\"color:#a6e22e\">types<\/span>: <span style=\"color:#66d9ef\">string<\/span>[] } {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">reducer<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">args<\/span>.<span style=\"color:#a6e22e\">pop<\/span>() <span style=\"color:#66d9ef\">as<\/span> Function;\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">types<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">args<\/span>.<span style=\"color:#a6e22e\">reduce<\/span>(\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#75715e\">\/\/ `creator.type` is a property directly attached to the function so that\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>    <span style=\"color:#75715e\">\/\/ it can be easily accessed(`createAction` is responsible for that)\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>    (<span style=\"color:#a6e22e\">result<\/span>, <span style=\"color:#a6e22e\">creator<\/span>) <span style=\"color:#f92672\">=&gt;<\/span> [...<span style=\"color:#a6e22e\">result<\/span>, (<span style=\"color:#a6e22e\">creator<\/span> <span style=\"color:#66d9ef\">as<\/span> <span style=\"color:#a6e22e\">ActionCreator<\/span>).<span style=\"color:#66d9ef\">type<\/span>],\n<\/span><\/span><span style=\"display:flex;\"><span>    [] <span style=\"color:#66d9ef\">as<\/span> <span style=\"color:#66d9ef\">string<\/span>[]\n<\/span><\/span><span style=\"display:flex;\"><span>  );\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">return<\/span> { <span style=\"color:#a6e22e\">reducer<\/span>, <span style=\"color:#a6e22e\">types<\/span> };\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p>The <code>createReducer<\/code> function will create a private <code>Map&lt;string, ActionReducer&lt;S, A&gt;&gt;<\/code> object, where the key is the <code>type<\/code> of the action, and the value is the corresponding reducer. It will also return a function whose arguments will be a given state and an action. Because it is a closure, it has access to the <code>Map<\/code> object.<\/p>\n<p>This function will be invoked every time an action is dispatched and what will do is to get the reducer based on the action type. Then, if the reducer is found, it will be called and will potentially return a new state.<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">export<\/span> <span style=\"color:#66d9ef\">interface<\/span> <span style=\"color:#a6e22e\">ActionReducer<\/span>&lt;<span style=\"color:#f92672\">T<\/span><span style=\"color:#960050;background-color:#1e0010\">,<\/span> <span style=\"color:#a6e22e\">V<\/span> <span style=\"color:#a6e22e\">extends<\/span> <span style=\"color:#a6e22e\">Action <\/span><span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">Action<\/span>&gt; {\n<\/span><\/span><span style=\"display:flex;\"><span>  (<span style=\"color:#a6e22e\">state<\/span>: <span style=\"color:#66d9ef\">T<\/span> <span style=\"color:#f92672\">|<\/span> <span style=\"color:#66d9ef\">undefined<\/span>, <span style=\"color:#a6e22e\">action<\/span>: <span style=\"color:#66d9ef\">V<\/span>)<span style=\"color:#f92672\">:<\/span> <span style=\"color:#a6e22e\">T<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">export<\/span> <span style=\"color:#66d9ef\">function<\/span> <span style=\"color:#a6e22e\">createReducer<\/span>&lt;<span style=\"color:#f92672\">S<\/span><span style=\"color:#960050;background-color:#1e0010\">,<\/span> <span style=\"color:#a6e22e\">A<\/span> <span style=\"color:#a6e22e\">extends<\/span> <span style=\"color:#a6e22e\">Action <\/span><span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">Action<\/span>&gt;(\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">initialState<\/span>: <span style=\"color:#66d9ef\">S<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>...<span style=\"color:#a6e22e\">ons<\/span>: <span style=\"color:#66d9ef\">On<\/span>&lt;<span style=\"color:#f92672\">S<\/span>&gt;[]\n<\/span><\/span><span style=\"display:flex;\"><span>)<span style=\"color:#f92672\">:<\/span> <span style=\"color:#a6e22e\">ActionReducer<\/span>&lt;<span style=\"color:#f92672\">S<\/span><span style=\"color:#960050;background-color:#1e0010\">,<\/span> <span style=\"color:#a6e22e\">A<\/span>&gt; {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">map<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">new<\/span> <span style=\"color:#a6e22e\">Map<\/span>&lt;<span style=\"color:#f92672\">string<\/span><span style=\"color:#960050;background-color:#1e0010\">,<\/span> <span style=\"color:#a6e22e\">ActionReducer<\/span><span style=\"color:#960050;background-color:#1e0010\">&lt;<\/span><span style=\"color:#a6e22e\">S<\/span><span style=\"color:#960050;background-color:#1e0010\">,<\/span> <span style=\"color:#a6e22e\">A<\/span>&gt;<span style=\"color:#f92672\">&gt;<\/span>();\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">for<\/span> (<span style=\"color:#66d9ef\">let<\/span> <span style=\"color:#a6e22e\">on<\/span> <span style=\"color:#66d9ef\">of<\/span> <span style=\"color:#a6e22e\">ons<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">for<\/span> (<span style=\"color:#66d9ef\">let<\/span> <span style=\"color:#66d9ef\">type<\/span> <span style=\"color:#66d9ef\">of<\/span> <span style=\"color:#a6e22e\">on<\/span>.<span style=\"color:#a6e22e\">types<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#a6e22e\">map<\/span>.<span style=\"color:#a6e22e\">has<\/span>(<span style=\"color:#66d9ef\">type<\/span>)) {\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">existingReducer<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">map<\/span>.<span style=\"color:#66d9ef\">get<\/span>(<span style=\"color:#66d9ef\">type<\/span>) <span style=\"color:#66d9ef\">as<\/span> <span style=\"color:#a6e22e\">ActionReducer<\/span>&lt;<span style=\"color:#f92672\">S<\/span><span style=\"color:#960050;background-color:#1e0010\">,<\/span> <span style=\"color:#a6e22e\">A<\/span>&gt;;\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">newReducer<\/span>: <span style=\"color:#66d9ef\">ActionReducer<\/span>&lt;<span style=\"color:#f92672\">S<\/span><span style=\"color:#960050;background-color:#1e0010\">,<\/span> <span style=\"color:#a6e22e\">A<\/span>&gt; <span style=\"color:#f92672\">=<\/span> (<span style=\"color:#a6e22e\">state<\/span>, <span style=\"color:#a6e22e\">action<\/span>) <span style=\"color:#f92672\">=&gt;<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>          <span style=\"color:#a6e22e\">on<\/span>.<span style=\"color:#a6e22e\">reducer<\/span>(<span style=\"color:#a6e22e\">existingReducer<\/span>(<span style=\"color:#a6e22e\">state<\/span>, <span style=\"color:#a6e22e\">action<\/span>), <span style=\"color:#a6e22e\">action<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#a6e22e\">map<\/span>.<span style=\"color:#66d9ef\">set<\/span>(<span style=\"color:#66d9ef\">type<\/span>, <span style=\"color:#a6e22e\">newReducer<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>      } <span style=\"color:#66d9ef\">else<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#a6e22e\">map<\/span>.<span style=\"color:#66d9ef\">set<\/span>(<span style=\"color:#66d9ef\">type<\/span>, <span style=\"color:#a6e22e\">on<\/span>.<span style=\"color:#a6e22e\">reducer<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>      }\n<\/span><\/span><span style=\"display:flex;\"><span>    }\n<\/span><\/span><span style=\"display:flex;\"><span>  }\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#66d9ef\">function<\/span>(<span style=\"color:#a6e22e\">state<\/span>: <span style=\"color:#66d9ef\">S<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">initialState<\/span>, <span style=\"color:#a6e22e\">action<\/span>: <span style=\"color:#66d9ef\">A<\/span>)<span style=\"color:#f92672\">:<\/span> <span style=\"color:#a6e22e\">S<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#75715e\">\/\/ This is the body of `_counterReducer` function from below\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>    <span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">reducer<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">map<\/span>.<span style=\"color:#66d9ef\">get<\/span>(<span style=\"color:#a6e22e\">action<\/span>.<span style=\"color:#66d9ef\">type<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#a6e22e\">reducer<\/span> <span style=\"color:#f92672\">?<\/span> <span style=\"color:#a6e22e\">reducer<\/span>(<span style=\"color:#a6e22e\">state<\/span>, <span style=\"color:#a6e22e\">action<\/span>) <span style=\"color:#f92672\">:<\/span> <span style=\"color:#a6e22e\">state<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>  };\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p>For instance, the <code>Map<\/code> object for the following <code>createReducer<\/code> reducer<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">increment<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">createAction<\/span>(<span style=\"color:#e6db74\">&#39;increment&#39;<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">decrement<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">createAction<\/span>(<span style=\"color:#e6db74\">&#39;decrement&#39;<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">reset<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">createAction<\/span>(<span style=\"color:#e6db74\">&#39;reset&#39;<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">_counterReducer<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">createReducer<\/span>(<span style=\"color:#a6e22e\">initialState<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">on<\/span>(<span style=\"color:#a6e22e\">increment<\/span>, <span style=\"color:#a6e22e\">state<\/span> <span style=\"color:#f92672\">=&gt;<\/span> <span style=\"color:#a6e22e\">state<\/span> <span style=\"color:#f92672\">+<\/span> <span style=\"color:#ae81ff\">1<\/span> <span style=\"color:#75715e\">\/* reducer#1 *\/<\/span>),\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">on<\/span>(<span style=\"color:#a6e22e\">decrement<\/span>, <span style=\"color:#a6e22e\">state<\/span> <span style=\"color:#f92672\">=&gt;<\/span> <span style=\"color:#a6e22e\">state<\/span> <span style=\"color:#f92672\">-<\/span> <span style=\"color:#ae81ff\">1<\/span> <span style=\"color:#75715e\">\/* reducer#2 *\/<\/span>),\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">on<\/span>(<span style=\"color:#a6e22e\">reset<\/span>, <span style=\"color:#a6e22e\">state<\/span> <span style=\"color:#f92672\">=&gt;<\/span> <span style=\"color:#ae81ff\">0<\/span> <span style=\"color:#75715e\">\/* reducer#3 *\/<\/span>),\n<\/span><\/span><span style=\"display:flex;\"><span>);\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">export<\/span> <span style=\"color:#66d9ef\">function<\/span> <span style=\"color:#a6e22e\">counterReducer<\/span>(<span style=\"color:#a6e22e\">state<\/span>, <span style=\"color:#a6e22e\">action<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#a6e22e\">_counterReducer<\/span>(<span style=\"color:#a6e22e\">state<\/span>, <span style=\"color:#a6e22e\">action<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p>will look like this:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span>{\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">key<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#34;increment&#34;<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">value<\/span>: <span style=\"color:#66d9ef\">\u0192<\/span> (<span style=\"color:#a6e22e\">state<\/span>) <span style=\"color:#75715e\">\/\/ reducer#1\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>},\n<\/span><\/span><span style=\"display:flex;\"><span>{\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">key<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#34;decrement&#34;<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">value<\/span>: <span style=\"color:#66d9ef\">\u0192<\/span> (<span style=\"color:#a6e22e\">state<\/span>) <span style=\"color:#75715e\">\/\/ reducer#2\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>},\n<\/span><\/span><span style=\"display:flex;\"><span>{\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">key<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#34;reset&#34;<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">value<\/span>: <span style=\"color:#66d9ef\">\u0192<\/span> (<span style=\"color:#a6e22e\">state<\/span>) <span style=\"color:#75715e\">\/\/ reducer#3\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>}\n<\/span><\/span><\/code><\/pre><\/div><p>The <code>createReducer<\/code>&rsquo;s returned function<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#66d9ef\">function<\/span>(<span style=\"color:#a6e22e\">state<\/span>: <span style=\"color:#66d9ef\">S<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">initialState<\/span>, <span style=\"color:#a6e22e\">action<\/span>: <span style=\"color:#66d9ef\">A<\/span>)<span style=\"color:#f92672\">:<\/span> <span style=\"color:#a6e22e\">S<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">reducer<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">map<\/span>.<span style=\"color:#66d9ef\">get<\/span>(<span style=\"color:#a6e22e\">action<\/span>.<span style=\"color:#66d9ef\">type<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#a6e22e\">reducer<\/span> <span style=\"color:#f92672\">?<\/span> <span style=\"color:#a6e22e\">reducer<\/span>(<span style=\"color:#a6e22e\">state<\/span>, <span style=\"color:#a6e22e\">action<\/span>) <span style=\"color:#f92672\">:<\/span> <span style=\"color:#a6e22e\">state<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>};\n<\/span><\/span><\/code><\/pre><\/div><p>will be called from <code>combination<\/code> function&rsquo;s body:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#66d9ef\">function<\/span> <span style=\"color:#a6e22e\">combination<\/span>(<span style=\"color:#a6e22e\">state<\/span>, <span style=\"color:#a6e22e\">action<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">for<\/span> (<span style=\"color:#66d9ef\">let<\/span> <span style=\"color:#a6e22e\">i<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#ae81ff\">0<\/span>; <span style=\"color:#a6e22e\">i<\/span> <span style=\"color:#f92672\">&lt;<\/span> <span style=\"color:#a6e22e\">finalReducerKeys<\/span>.<span style=\"color:#a6e22e\">length<\/span>; <span style=\"color:#a6e22e\">i<\/span><span style=\"color:#f92672\">++<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#75715e\">\/* ... *\/<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">reducer<\/span>: <span style=\"color:#66d9ef\">any<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">finalReducers<\/span>[<span style=\"color:#a6e22e\">key<\/span>];\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">nextStateForKey<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">reducer<\/span>(<span style=\"color:#a6e22e\">previousStateForKey<\/span>, <span style=\"color:#a6e22e\">action<\/span>); <span style=\"color:#75715e\">\/\/ &lt;- Here!\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#75715e\">\/* ... *\/<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>  }\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#75715e\">\/* ... *\/<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>};\n<\/span><\/span><\/code><\/pre><\/div><p>The <code>on<\/code> function can <em>bind<\/em> a reducer to multiple actions. Then, in the reducer, with the help of discriminated unions, we can perform the appropriate state change depending on action.<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">a1<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">createAction<\/span>(<span style=\"color:#e6db74\">&#39;a1&#39;<\/span>, <span style=\"color:#a6e22e\">props<\/span><span style=\"color:#f92672\">&lt;<\/span>{ <span style=\"color:#a6e22e\">name<\/span>: <span style=\"color:#66d9ef\">string<\/span> }<span style=\"color:#f92672\">&gt;<\/span>());\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">a2<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">createAction<\/span>(<span style=\"color:#e6db74\">&#39;a2&#39;<\/span>, <span style=\"color:#a6e22e\">props<\/span><span style=\"color:#f92672\">&lt;<\/span>{ <span style=\"color:#a6e22e\">age<\/span>: <span style=\"color:#66d9ef\">number<\/span> }<span style=\"color:#f92672\">&gt;<\/span>());\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">initialState<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#75715e\">\/* ... *\/<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">reducer<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">createReducer<\/span>(\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">initialState<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">on<\/span>(<span style=\"color:#a6e22e\">a1<\/span>, <span style=\"color:#a6e22e\">a2<\/span>, (<span style=\"color:#a6e22e\">state<\/span>, <span style=\"color:#a6e22e\">action<\/span>) <span style=\"color:#f92672\">=&gt;<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#a6e22e\">action<\/span>.<span style=\"color:#66d9ef\">type<\/span> <span style=\"color:#f92672\">===<\/span> <span style=\"color:#e6db74\">&#39;a1&#39;<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#a6e22e\">action<\/span>.<span style=\"color:#a6e22e\">name<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>    } <span style=\"color:#66d9ef\">else<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#a6e22e\">action<\/span>.<span style=\"color:#a6e22e\">age<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>    }\n<\/span><\/span><span style=\"display:flex;\"><span>  }),\n<\/span><\/span><span style=\"display:flex;\"><span>)\n<\/span><\/span><\/code><\/pre><\/div><p>Here\u2019s why this is possible:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">export<\/span> <span style=\"color:#66d9ef\">function<\/span> <span style=\"color:#a6e22e\">on<\/span>&lt;<span style=\"color:#f92672\">C1<\/span> <span style=\"color:#a6e22e\">extends<\/span> <span style=\"color:#a6e22e\">ActionCreator<\/span><span style=\"color:#960050;background-color:#1e0010\">,<\/span> <span style=\"color:#a6e22e\">C2<\/span> <span style=\"color:#a6e22e\">extends<\/span> <span style=\"color:#a6e22e\">ActionCreator<\/span><span style=\"color:#960050;background-color:#1e0010\">,<\/span> <span style=\"color:#a6e22e\">S<\/span>&gt;(\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">creator1<\/span>: <span style=\"color:#66d9ef\">C1<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">creator2<\/span>: <span style=\"color:#66d9ef\">C2<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">reducer<\/span>: <span style=\"color:#66d9ef\">OnReducer<\/span>&lt;<span style=\"color:#f92672\">S<\/span><span style=\"color:#960050;background-color:#1e0010\">,<\/span> <span style=\"color:#960050;background-color:#1e0010\">[<\/span><span style=\"color:#a6e22e\">C1<\/span><span style=\"color:#960050;background-color:#1e0010\">,<\/span> <span style=\"color:#a6e22e\">C2<\/span><span style=\"color:#960050;background-color:#1e0010\">]<\/span>&gt;\n<\/span><\/span><span style=\"display:flex;\"><span>)<span style=\"color:#f92672\">:<\/span> <span style=\"color:#a6e22e\">On<\/span>&lt;<span style=\"color:#f92672\">S<\/span>&gt;;\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ `C[number]` will result in a union\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span><span style=\"color:#66d9ef\">export<\/span> <span style=\"color:#66d9ef\">interface<\/span> <span style=\"color:#a6e22e\">OnReducer<\/span>&lt;<span style=\"color:#f92672\">S<\/span><span style=\"color:#960050;background-color:#1e0010\">,<\/span> <span style=\"color:#a6e22e\">C<\/span> <span style=\"color:#a6e22e\">extends<\/span> <span style=\"color:#a6e22e\">ActionCreator<\/span><span style=\"color:#960050;background-color:#1e0010\">[]<\/span>&gt; {\n<\/span><\/span><span style=\"display:flex;\"><span>  (<span style=\"color:#a6e22e\">state<\/span>: <span style=\"color:#66d9ef\">S<\/span>, <span style=\"color:#a6e22e\">action<\/span>: <span style=\"color:#66d9ef\">ActionType<\/span>&lt;<span style=\"color:#f92672\">C<\/span><span style=\"color:#960050;background-color:#1e0010\">[<\/span><span style=\"color:#a6e22e\">number<\/span><span style=\"color:#960050;background-color:#1e0010\">]<\/span>&gt;)<span style=\"color:#f92672\">:<\/span> <span style=\"color:#a6e22e\">S<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p>Also, it is worth mentioning that the entire State type will be inferred from what is being passed as <code>initialState<\/code>:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">export<\/span> <span style=\"color:#66d9ef\">function<\/span> <span style=\"color:#a6e22e\">createReducer<\/span>&lt;<span style=\"color:#f92672\">S<\/span><span style=\"color:#960050;background-color:#1e0010\">,<\/span> <span style=\"color:#a6e22e\">A<\/span> <span style=\"color:#a6e22e\">extends<\/span> <span style=\"color:#a6e22e\">Action <\/span><span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">Action<\/span>&gt;(\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">initialState<\/span>: <span style=\"color:#66d9ef\">S<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  ...<span style=\"color:#a6e22e\">ons<\/span>: <span style=\"color:#66d9ef\">On<\/span>&lt;<span style=\"color:#f92672\">S<\/span>&gt;[]\n<\/span><\/span><span style=\"display:flex;\"><span>)<span style=\"color:#f92672\">:<\/span> <span style=\"color:#a6e22e\">ActionReducer<\/span>&lt;<span style=\"color:#f92672\">S<\/span><span style=\"color:#960050;background-color:#1e0010\">,<\/span> <span style=\"color:#a6e22e\">A<\/span>&gt; { <span style=\"color:#75715e\">\/* ... *\/<\/span> }\n<\/span><\/span><\/code><\/pre><\/div><p><a href=\"https:\/\/www.typescriptlang.org\/play\/#code\/JYOwLgpgTgZghgYwgAgIILMA9iZBvAKGWSgjgBMcAbAT2TBoAcIAuZAZzClAHMBuAgF8CBUJFiIUqAIz4i9Jq2QByONOUAaeSDgBbJZ24h&#43;QkWOjwkaAExziDZm1XXN8uDyUgArroBG0AWECBxQAcQgwAFUQbBAAHlRkCAAPSBBydjQMWIBtAF0APmQAXjQc7z9oPIFgxWRo2JLkcKiYnDicmQ0bQpqEHE5kLDYGnCbCe0UnNVdiHX1p9NJgWeQAejXkdyVpawBmZABaIugoLCghIA\" target=\"_blank\" rel=\"noopener\"><em>TypeScript Playground<\/em><\/a>.<\/p>\n<p>Another great feature that <code>createReducer<\/code> comes with is composability. You can use the same action with multiple reducers. What this means is that an <code>n<\/code>th <code>on<\/code>&rsquo;s reducer state which has an action <code>a<\/code> will be result of the <code>n-1<\/code>th <code>on<\/code>&rsquo;s reducer that has the same action <code>a<\/code>:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">export<\/span> <span style=\"color:#66d9ef\">function<\/span> <span style=\"color:#a6e22e\">createReducer<\/span>&lt;<span style=\"color:#f92672\">S<\/span><span style=\"color:#960050;background-color:#1e0010\">,<\/span> <span style=\"color:#a6e22e\">A<\/span> <span style=\"color:#a6e22e\">extends<\/span> <span style=\"color:#a6e22e\">Action <\/span><span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">Action<\/span>&gt;(\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">initialState<\/span>: <span style=\"color:#66d9ef\">S<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  ...<span style=\"color:#a6e22e\">ons<\/span>: <span style=\"color:#66d9ef\">On<\/span>&lt;<span style=\"color:#f92672\">S<\/span>&gt;[]\n<\/span><\/span><span style=\"display:flex;\"><span>)<span style=\"color:#f92672\">:<\/span> <span style=\"color:#a6e22e\">ActionReducer<\/span>&lt;<span style=\"color:#f92672\">S<\/span><span style=\"color:#960050;background-color:#1e0010\">,<\/span> <span style=\"color:#a6e22e\">A<\/span>&gt; {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">map<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">new<\/span> <span style=\"color:#a6e22e\">Map<\/span>&lt;<span style=\"color:#f92672\">string<\/span><span style=\"color:#960050;background-color:#1e0010\">,<\/span> <span style=\"color:#a6e22e\">ActionReducer<\/span><span style=\"color:#960050;background-color:#1e0010\">&lt;<\/span><span style=\"color:#a6e22e\">S<\/span><span style=\"color:#960050;background-color:#1e0010\">,<\/span> <span style=\"color:#a6e22e\">A<\/span>&gt;<span style=\"color:#f92672\">&gt;<\/span>();\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">for<\/span> (<span style=\"color:#66d9ef\">let<\/span> <span style=\"color:#a6e22e\">on<\/span> <span style=\"color:#66d9ef\">of<\/span> <span style=\"color:#a6e22e\">ons<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">for<\/span> (<span style=\"color:#66d9ef\">let<\/span> <span style=\"color:#66d9ef\">type<\/span> <span style=\"color:#66d9ef\">of<\/span> <span style=\"color:#a6e22e\">on<\/span>.<span style=\"color:#a6e22e\">types<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#a6e22e\">map<\/span>.<span style=\"color:#a6e22e\">has<\/span>(<span style=\"color:#66d9ef\">type<\/span>)) {\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#75715e\">\/\/ Getting the previous reducer(`n-1`)\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>        <span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">existingReducer<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">map<\/span>.<span style=\"color:#66d9ef\">get<\/span>(<span style=\"color:#66d9ef\">type<\/span>) <span style=\"color:#66d9ef\">as<\/span> <span style=\"color:#a6e22e\">ActionReducer<\/span>&lt;<span style=\"color:#f92672\">S<\/span><span style=\"color:#960050;background-color:#1e0010\">,<\/span> <span style=\"color:#a6e22e\">A<\/span>&gt;;\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#75715e\">\/\/ The new reducer&#39;s state will be the result of the previous reducer&#39;s result\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>        <span style=\"color:#75715e\">\/\/ n = n(n-1(state, action),  action)\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>        <span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">newReducer<\/span>: <span style=\"color:#66d9ef\">ActionReducer<\/span>&lt;<span style=\"color:#f92672\">S<\/span><span style=\"color:#960050;background-color:#1e0010\">,<\/span> <span style=\"color:#a6e22e\">A<\/span>&gt; <span style=\"color:#f92672\">=<\/span> (<span style=\"color:#a6e22e\">state<\/span>, <span style=\"color:#a6e22e\">action<\/span>) <span style=\"color:#f92672\">=&gt;<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>          <span style=\"color:#a6e22e\">on<\/span>.<span style=\"color:#a6e22e\">reducer<\/span>(<span style=\"color:#a6e22e\">existingReducer<\/span>(<span style=\"color:#a6e22e\">state<\/span>, <span style=\"color:#a6e22e\">action<\/span>), <span style=\"color:#a6e22e\">action<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#a6e22e\">map<\/span>.<span style=\"color:#66d9ef\">set<\/span>(<span style=\"color:#66d9ef\">type<\/span>, <span style=\"color:#a6e22e\">newReducer<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>      } <span style=\"color:#66d9ef\">else<\/span> { <span style=\"color:#75715e\">\/* ... *\/<\/span> }\n<\/span><\/span><span style=\"display:flex;\"><span>    }\n<\/span><\/span><span style=\"display:flex;\"><span>  }\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#66d9ef\">function<\/span>(<span style=\"color:#a6e22e\">state<\/span>: <span style=\"color:#66d9ef\">S<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">initialState<\/span>, <span style=\"color:#a6e22e\">action<\/span>: <span style=\"color:#66d9ef\">A<\/span>)<span style=\"color:#f92672\">:<\/span> <span style=\"color:#a6e22e\">S<\/span> { <span style=\"color:#75715e\">\/* ... *\/<\/span> };\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p>Here\u2019s an example:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">a1<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">createAction<\/span>(<span style=\"color:#e6db74\">&#39;a1&#39;<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">a2<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">createAction<\/span>(<span style=\"color:#e6db74\">&#39;a2&#39;<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">reducer<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">createReducer<\/span>(\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#ae81ff\">0<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">on<\/span>(<span style=\"color:#a6e22e\">a1<\/span>, <span style=\"color:#a6e22e\">state<\/span> <span style=\"color:#f92672\">=&gt;<\/span> <span style=\"color:#a6e22e\">state<\/span> <span style=\"color:#f92672\">+<\/span> <span style=\"color:#ae81ff\">2<\/span> <span style=\"color:#75715e\">\/* reducer1 *\/<\/span>),\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">on<\/span>(<span style=\"color:#a6e22e\">a1<\/span>, <span style=\"color:#a6e22e\">state<\/span> <span style=\"color:#f92672\">=&gt;<\/span> <span style=\"color:#a6e22e\">state<\/span> <span style=\"color:#f92672\">**<\/span> <span style=\"color:#ae81ff\">2<\/span> <span style=\"color:#75715e\">\/* reducer2 *\/<\/span>),\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">on<\/span>(<span style=\"color:#a6e22e\">a1<\/span>, <span style=\"color:#a6e22e\">state<\/span> <span style=\"color:#f92672\">=&gt;<\/span> <span style=\"color:#a6e22e\">state<\/span> <span style=\"color:#f92672\">*<\/span> <span style=\"color:#ae81ff\">10<\/span> <span style=\"color:#75715e\">\/* reducer3 *\/<\/span>)\n<\/span><\/span><span style=\"display:flex;\"><span>);\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">console<\/span>.<span style=\"color:#a6e22e\">log<\/span>(<span style=\"color:#a6e22e\">reducer<\/span>(<span style=\"color:#66d9ef\">undefined<\/span>, <span style=\"color:#a6e22e\">a1<\/span>)); <span style=\"color:#75715e\">\/\/ 40\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ The above is similar to this:\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span><span style=\"color:#a6e22e\">reducer3<\/span>(<span style=\"color:#a6e22e\">reducer2<\/span>(<span style=\"color:#a6e22e\">reducer1<\/span>(<span style=\"color:#ae81ff\">0<\/span>)));\n<\/span><\/span><\/code><\/pre><\/div><h2 id=\"store\">\n  <span>\n  Store\n  <\/span>\n  <a href=\"#store\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><p>This is one of the <code>ngrx\/store<\/code>&rsquo;s foundations. This is not the place where the information is kept, but rather a bridge between the data consumer (a smart component) and the place where the information is kept (the <code>State<\/code> entity).<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">export<\/span> <span style=\"color:#66d9ef\">class<\/span> <span style=\"color:#a6e22e\">Store<\/span>&lt;<span style=\"color:#f92672\">T<\/span>&gt; <span style=\"color:#66d9ef\">extends<\/span> <span style=\"color:#a6e22e\">Observable<\/span>&lt;<span style=\"color:#f92672\">T<\/span>&gt; <span style=\"color:#66d9ef\">implements<\/span> <span style=\"color:#a6e22e\">Observer<\/span>&lt;<span style=\"color:#f92672\">Action<\/span>&gt; {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">constructor<\/span>(\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">state$<\/span>: <span style=\"color:#66d9ef\">StateObservable<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">private<\/span> <span style=\"color:#a6e22e\">actionsObserver<\/span>: <span style=\"color:#66d9ef\">ActionsSubject<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">private<\/span> <span style=\"color:#a6e22e\">reducerManager<\/span>: <span style=\"color:#66d9ef\">ReducerManager<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>  ) {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">super<\/span>();\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">source<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">state$<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>  }\n<\/span><\/span><span style=\"display:flex;\"><span>  \n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#75715e\">\/* ... *\/<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p>From the above snippet we can tell that the <code>Store<\/code> class is a hot observable because the data it emits comes from outside, namely <code>state$<\/code>. This means that every time the <code>source<\/code> (<code>state$<\/code>) emits, the <code>Store<\/code> class will send the value to <em>its subscribers<\/em>. This is possible because <code>state$<\/code> extends <code>BehaviorSubject<\/code> and by setting this as a source to any other observable, whenever that observable is subscribed to, that observer(subscriber) will be added to the subscribers list maintained by the <code>BehaviorSubject<\/code>. Here\u2019s an example which illustrates these facts:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">s<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">new<\/span> <span style=\"color:#a6e22e\">Subject<\/span>();\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">class<\/span> <span style=\"color:#a6e22e\">Custom<\/span> <span style=\"color:#66d9ef\">extends<\/span> <span style=\"color:#a6e22e\">Observable<\/span>&lt;<span style=\"color:#f92672\">any<\/span>&gt; {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">constructor<\/span> () {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">super<\/span>();\n<\/span><\/span><span style=\"display:flex;\"><span>    \n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#75715e\">\/\/ By doing this, every time you do `customInstance.subscribe(subscriber)`,\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>    <span style=\"color:#75715e\">\/\/ the subscriber wll be part of the subject&#39;s subscribers list\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>    <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">source<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">s<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>  }\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">obs$<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">new<\/span> <span style=\"color:#a6e22e\">Custom<\/span>();\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ The subject has no subscribers at this point\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span><span style=\"color:#a6e22e\">s<\/span>.<span style=\"color:#a6e22e\">next<\/span>(<span style=\"color:#e6db74\">&#39;no&#39;<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ The subject has one subscriber now\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span><span style=\"color:#a6e22e\">obs$<\/span>.<span style=\"color:#a6e22e\">subscribe<\/span>(<span style=\"color:#a6e22e\">console<\/span>.<span style=\"color:#a6e22e\">log<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ `s.next()` -&gt; sending values to the active subscribers\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span><span style=\"color:#a6e22e\">timer<\/span>(<span style=\"color:#ae81ff\">1000<\/span>)\n<\/span><\/span><span style=\"display:flex;\"><span>  .<span style=\"color:#a6e22e\">subscribe<\/span>(() <span style=\"color:#f92672\">=&gt;<\/span> <span style=\"color:#a6e22e\">s<\/span>.<span style=\"color:#a6e22e\">next<\/span>(<span style=\"color:#e6db74\">&#39;john&#39;<\/span>));\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">timer<\/span>(<span style=\"color:#ae81ff\">2000<\/span>)\n<\/span><\/span><span style=\"display:flex;\"><span>  .<span style=\"color:#a6e22e\">subscribe<\/span>(() <span style=\"color:#f92672\">=&gt;<\/span> <span style=\"color:#a6e22e\">s<\/span>.<span style=\"color:#a6e22e\">next<\/span>(<span style=\"color:#e6db74\">&#39;doe&#39;<\/span>));\n<\/span><\/span><\/code><\/pre><\/div><p><a href=\"https:\/\/medium.com\/r\/?url=https%3A%2F%2Fstackblitz.com%2Fedit%2Fmanual-set-source%3Ffile%3Dindex.ts\" target=\"_blank\" rel=\"noopener\"><em>StackBlitz.<\/em><\/a><\/p>\n<p>It is worth noticing the presence of <code>ActionsSubject<\/code>, with which we are able to push values in the action stream whenever the <code>Store.dispatch<\/code> is called.<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">dispatch<\/span>&lt;<span style=\"color:#f92672\">V<\/span> <span style=\"color:#a6e22e\">extends<\/span> <span style=\"color:#a6e22e\">Action <\/span><span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">Action<\/span>&gt;(\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">action<\/span>: <span style=\"color:#66d9ef\">V<\/span> <span style=\"color:#75715e\">\/* ... type check here - skipped for brevity ... *\/<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">actionsObserver<\/span>.<span style=\"color:#a6e22e\">next<\/span>(<span style=\"color:#a6e22e\">action<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p>You can think of this <code>Store<\/code> class as a dispatcher, because it can dispatch actions with <code>Store.dispatch(action)<\/code>, but you can also think of it as a data receiver, because you can be notified about changes in the state is by subscribing to a <code>Store<\/code> instance(<code>Store.subscribe()<\/code>).<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-markdown\" data-lang=\"markdown\"><span style=\"display:flex;\"><span>allows consumer \u2194\ufe0f state communication\n<\/span><\/span><span style=\"display:flex;\"><span>        \u2b06\ufe0f\n<\/span><\/span><span style=\"display:flex;\"><span>        |\n<\/span><\/span><span style=\"display:flex;\"><span>        |\n<\/span><\/span><span style=\"display:flex;\"><span>-----------\u2008     newState          -----------\u2008                        \n<\/span><\/span><span style=\"display:flex;\"><span>|         |\u2008&lt;<span style=\"color:#f92672\">-------------------<\/span>   <span style=\"color:#960050;background-color:#1e0010\">|<\/span>         <span style=\"color:#960050;background-color:#1e0010\">|<\/span>\u2008                        \n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#960050;background-color:#1e0010\">|<\/span>         <span style=\"color:#960050;background-color:#1e0010\">|<\/span>\u2008 <span style=\"color:#a6e22e\">Store<\/span><span style=\"color:#960050;background-color:#1e0010\">.<\/span><span style=\"color:#a6e22e\">source<\/span><span style=\"color:#f92672\">=<\/span><span style=\"color:#e6db74\">$state<\/span>   <span style=\"color:#960050;background-color:#1e0010\">|<\/span>         <span style=\"color:#960050;background-color:#1e0010\">|<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#960050;background-color:#1e0010\">|<\/span>         <span style=\"color:#960050;background-color:#1e0010\">|<\/span>                    \u2008   <span style=\"color:#960050;background-color:#1e0010\">|<\/span>         <span style=\"color:#960050;background-color:#1e0010\">|<\/span> <span style=\"color:#960050;background-color:#1e0010\">&lt;<\/span><span style=\"color:#a6e22e\">----<\/span> <span style=\"color:#a6e22e\">storing<\/span> <span style=\"color:#a6e22e\">data<\/span> \n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#960050;background-color:#1e0010\">|<\/span>  <span style=\"color:#a6e22e\">Store<\/span>  <span style=\"color:#960050;background-color:#1e0010\">|<\/span>\u2008     <span style=\"color:#a6e22e\">Action<\/span>            <span style=\"color:#960050;background-color:#1e0010\">|<\/span>  <span style=\"color:#a6e22e\">State<\/span>  <span style=\"color:#960050;background-color:#1e0010\">|<\/span>\u2008                        \n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#960050;background-color:#1e0010\">|<\/span>         <span style=\"color:#960050;background-color:#1e0010\">|<\/span> <span style=\"color:#a6e22e\">--------------------<\/span>&gt;\u2008 |         |\n<\/span><\/span><span style=\"display:flex;\"><span>|         |\u2008  Store.dispatch()     |         |\u2008         \n<\/span><\/span><span style=\"display:flex;\"><span>-----------\u2008                       -----------\u2008\n<\/span><\/span><span style=\"display:flex;\"><span>                                   |        \u2b06\ufe0f\n<\/span><\/span><span style=\"display:flex;\"><span>                          Action   |        | newState\n<\/span><\/span><span style=\"display:flex;\"><span>                                   |        |\n<\/span><\/span><span style=\"display:flex;\"><span>                                   \u2b07\ufe0f        |\n<\/span><\/span><span style=\"display:flex;\"><span>                                  -------------\u2008\n<\/span><\/span><span style=\"display:flex;\"><span>                                  |           |\u2008\n<\/span><\/span><span style=\"display:flex;\"><span>                                  |  Reducer  |\u2008&lt;<span style=\"color:#f92672\">----<\/span> <span style=\"color:#a6e22e\">state<\/span> <span style=\"color:#a6e22e\">changes<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>                                  <span style=\"color:#960050;background-color:#1e0010\">|<\/span>           <span style=\"color:#960050;background-color:#1e0010\">|<\/span>\u2008\n<\/span><\/span><span style=\"display:flex;\"><span>                                  <span style=\"color:#a6e22e\">-------------<\/span>\n<\/span><\/span><\/code><\/pre><\/div><p>So, the <code>State<\/code> class is the place where <em>actions meet reducers<\/em>, where the reducers are called with the existing state and based on the action, it will generate and emit a new state through the <code>Store<\/code>(because the <code>Store<\/code>&rsquo;s source is the <code>State<\/code> itself).<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">export<\/span> <span style=\"color:#66d9ef\">class<\/span> <span style=\"color:#a6e22e\">State<\/span>&lt;<span style=\"color:#f92672\">T<\/span>&gt; <span style=\"color:#66d9ef\">extends<\/span> <span style=\"color:#a6e22e\">BehaviorSubject<\/span>&lt;<span style=\"color:#f92672\">any<\/span>&gt; <span style=\"color:#66d9ef\">implements<\/span> <span style=\"color:#a6e22e\">OnDestroy<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">constructor<\/span>(\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">actions$<\/span>: <span style=\"color:#66d9ef\">ActionsSubject<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">reducer$<\/span>: <span style=\"color:#66d9ef\">ReducerObservable<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">scannedActions<\/span>: <span style=\"color:#66d9ef\">ScannedActionsSubject<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">@Inject<\/span>(<span style=\"color:#a6e22e\">INITIAL_STATE<\/span>) <span style=\"color:#a6e22e\">initialState<\/span>: <span style=\"color:#66d9ef\">any<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>  ) { \n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#75715e\">\/* ... *\/<\/span> \n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">stateSubscription<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">stateAndAction$<\/span>.<span style=\"color:#a6e22e\">subscribe<\/span>(({ <span style=\"color:#a6e22e\">state<\/span>, <span style=\"color:#a6e22e\">action<\/span> }) <span style=\"color:#f92672\">=&gt;<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">next<\/span>(<span style=\"color:#a6e22e\">state<\/span>); <span style=\"color:#75715e\">\/\/ Emitting the new state\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>      <span style=\"color:#a6e22e\">scannedActions<\/span>.<span style=\"color:#a6e22e\">next<\/span>(<span style=\"color:#a6e22e\">action<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>    });\n<\/span><\/span><span style=\"display:flex;\"><span>  }\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#75715e\">\/* ... *\/<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p>I\u2019d see the <code>Store<\/code> class as some sort of middleman between the <code>Model<\/code>(the place where the data is actually stored) and the <code>Data Consumer<\/code>:<\/p>\n<p><code>Data Consumer<\/code> -&gt; <code>Model<\/code>: <code>Store.dispatch()<\/code><br>\n<code>Model<\/code> -&gt; <code>Data Consumer<\/code>: <code>Store.subscribe()<\/code><\/p>\n<p>As a side note, <code>Store<\/code> can not only be used as an observable, but also as an observer(e.g: when intercepting actions emitted by the effects).<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">next<\/span>(<span style=\"color:#a6e22e\">action<\/span>: <span style=\"color:#66d9ef\">Action<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">actionsObserver<\/span>.<span style=\"color:#a6e22e\">next<\/span>(<span style=\"color:#a6e22e\">action<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">error<\/span>(<span style=\"color:#a6e22e\">err<\/span>: <span style=\"color:#66d9ef\">any<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">actionsObserver<\/span>.<span style=\"color:#a6e22e\">error<\/span>(<span style=\"color:#a6e22e\">err<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">complete() {<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">actionsObserver<\/span>.<span style=\"color:#a6e22e\">complete<\/span>();\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p>This might also come in handy when you can\u2019t know which action and when you\u2019ll want to dispatch.<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">actions$<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">of<\/span>(<span style=\"color:#a6e22e\">FooActions<\/span>.<span style=\"color:#a6e22e\">add<\/span>({ <span style=\"color:#a6e22e\">age<\/span>: <span style=\"color:#66d9ef\">18<\/span>, <span style=\"color:#a6e22e\">name<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;andrei&#39;<\/span> }));\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">actions$<\/span>.<span style=\"color:#a6e22e\">subscribe<\/span>(<span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">store<\/span>)\n<\/span><\/span><\/code><\/pre><\/div><h3 id=\"selecting-from-the-store\">\n  <span>\n  Selecting from the Store\n  <\/span>\n  <a href=\"#selecting-from-the-store\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h3><p>Because <code>Store<\/code>&rsquo;s source is <code>State<\/code> , which is where the data is kept, selecting from the store and receiving eventual updates is a seamless operation.<\/p>\n<p>We can use both <code>Store.select('path' | customSelector)<\/code>:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">export<\/span> <span style=\"color:#66d9ef\">class<\/span> <span style=\"color:#a6e22e\">Store<\/span>&lt;<span style=\"color:#f92672\">T<\/span>&gt; <span style=\"color:#75715e\">\/* ... *\/<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">select<\/span>&lt;<span style=\"color:#f92672\">Props<\/span> <span style=\"color:#960050;background-color:#1e0010\">=<\/span> <span style=\"color:#a6e22e\">any<\/span><span style=\"color:#960050;background-color:#1e0010\">,<\/span> <span style=\"color:#a6e22e\">K <\/span><span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">any<\/span>&gt;(\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">pathOrMapFn<\/span><span style=\"color:#f92672\">:<\/span> ((<span style=\"color:#a6e22e\">state<\/span>: <span style=\"color:#66d9ef\">T<\/span>, <span style=\"color:#a6e22e\">props?<\/span>: <span style=\"color:#66d9ef\">Props<\/span>) <span style=\"color:#f92672\">=&gt;<\/span> <span style=\"color:#a6e22e\">K<\/span>) <span style=\"color:#f92672\">|<\/span> <span style=\"color:#66d9ef\">string<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>    ...<span style=\"color:#a6e22e\">paths<\/span>: <span style=\"color:#66d9ef\">string<\/span>[]\n<\/span><\/span><span style=\"display:flex;\"><span>  )<span style=\"color:#f92672\">:<\/span> <span style=\"color:#a6e22e\">Observable<\/span>&lt;<span style=\"color:#f92672\">any<\/span>&gt; {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">return<\/span> (<span style=\"color:#a6e22e\">select<\/span> <span style=\"color:#66d9ef\">as<\/span> <span style=\"color:#66d9ef\">any<\/span>).<span style=\"color:#a6e22e\">call<\/span>(<span style=\"color:#66d9ef\">null<\/span>, <span style=\"color:#a6e22e\">pathOrMapFn<\/span>, ...<span style=\"color:#a6e22e\">paths<\/span>)(<span style=\"color:#66d9ef\">this<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>  }\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">export<\/span> <span style=\"color:#66d9ef\">function<\/span> <span style=\"color:#a6e22e\">select<\/span>&lt;<span style=\"color:#f92672\">T<\/span><span style=\"color:#960050;background-color:#1e0010\">,<\/span> <span style=\"color:#a6e22e\">Props<\/span><span style=\"color:#960050;background-color:#1e0010\">,<\/span> <span style=\"color:#a6e22e\">K<\/span>&gt;(\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">pathOrMapFn<\/span><span style=\"color:#f92672\">:<\/span> ((<span style=\"color:#a6e22e\">state<\/span>: <span style=\"color:#66d9ef\">T<\/span>, <span style=\"color:#a6e22e\">props?<\/span>: <span style=\"color:#66d9ef\">Props<\/span>) <span style=\"color:#f92672\">=&gt;<\/span> <span style=\"color:#66d9ef\">any<\/span>) <span style=\"color:#f92672\">|<\/span> <span style=\"color:#66d9ef\">string<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">propsOrPath?<\/span>: <span style=\"color:#66d9ef\">Props<\/span> <span style=\"color:#f92672\">|<\/span> <span style=\"color:#66d9ef\">string<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  ...<span style=\"color:#a6e22e\">paths<\/span>: <span style=\"color:#66d9ef\">string<\/span>[]\n<\/span><\/span><span style=\"display:flex;\"><span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#66d9ef\">function<\/span> <span style=\"color:#a6e22e\">selectOperator<\/span>(<span style=\"color:#a6e22e\">source$<\/span>: <span style=\"color:#66d9ef\">Observable<\/span>&lt;<span style=\"color:#f92672\">T<\/span>&gt;)<span style=\"color:#f92672\">:<\/span> <span style=\"color:#a6e22e\">Observable<\/span>&lt;<span style=\"color:#f92672\">K<\/span>&gt; {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">let<\/span> <span style=\"color:#a6e22e\">mapped$<\/span>: <span style=\"color:#66d9ef\">Observable<\/span>&lt;<span style=\"color:#f92672\">any<\/span>&gt;;\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#75715e\">\/* ... Important logic here ... *\/<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#a6e22e\">mapped$<\/span>.<span style=\"color:#a6e22e\">pipe<\/span>(<span style=\"color:#a6e22e\">distinctUntilChanged<\/span>());\n<\/span><\/span><span style=\"display:flex;\"><span>  };\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p>or <code>Store.pipe(select('path') | select(customSelector))<\/code>. As you can see, both approaches will make use of the <code>select<\/code> function and will return an observable.<\/p>\n<p>Assuming you have have a state that complies with this interface:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">interface<\/span> <span style=\"color:#a6e22e\">AppState<\/span> { <span style=\"color:#a6e22e\">foo<\/span>: <span style=\"color:#66d9ef\">Foo<\/span>; }\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">interface<\/span> <span style=\"color:#a6e22e\">Foo<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">fooUsers<\/span>: <span style=\"color:#66d9ef\">User<\/span>[];\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">prop1<\/span>: <span style=\"color:#66d9ef\">string<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">prop2<\/span>: <span style=\"color:#66d9ef\">number<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">interface<\/span> <span style=\"color:#a6e22e\">User<\/span> { <span style=\"color:#a6e22e\">name<\/span>: <span style=\"color:#66d9ef\">string<\/span>; <span style=\"color:#a6e22e\">age<\/span>: <span style=\"color:#66d9ef\">number<\/span>; }\n<\/span><\/span><\/code><\/pre><\/div><p>you could inject the store like this:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">export<\/span> <span style=\"color:#66d9ef\">class<\/span> <span style=\"color:#a6e22e\">SmartComponent<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">constructor<\/span> (<span style=\"color:#66d9ef\">private<\/span> <span style=\"color:#a6e22e\">store<\/span>: <span style=\"color:#66d9ef\">Store<\/span>&lt;<span style=\"color:#f92672\">AppState<\/span>&gt;) { }\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p>There are a couple of ways to fetch data from the store.<\/p>\n<h4 id=\"provide-the-path-of-the-slice-were-interested-in-with-the-help-of-a-sequence-of-string-values\">\n  <span>\n  Provide the path of the slice we\u2019re interested in with the help of a sequence of string values\n  <\/span>\n  <a href=\"#provide-the-path-of-the-slice-were-interested-in-with-the-help-of-a-sequence-of-string-values\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h4><div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">store<\/span>.<span style=\"color:#a6e22e\">select<\/span>(<span style=\"color:#e6db74\">&#39;foo&#39;<\/span>, <span style=\"color:#e6db74\">&#39;fooUsers&#39;<\/span>, <span style=\"color:#75715e\">\/* ... *\/<\/span>)\n<\/span><\/span><span style=\"display:flex;\"><span>  .<span style=\"color:#a6e22e\">subscribe<\/span>(<span style=\"color:#a6e22e\">console<\/span>.<span style=\"color:#a6e22e\">log<\/span>)\n<\/span><\/span><\/code><\/pre><\/div><p>The <code>select<\/code> function is filled up with multiple overloads:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">export<\/span> <span style=\"color:#66d9ef\">function<\/span> <span style=\"color:#a6e22e\">select<\/span><span style=\"color:#f92672\">&lt;<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">T<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">a<\/span> <span style=\"color:#66d9ef\">extends<\/span> <span style=\"color:#66d9ef\">keyof<\/span> <span style=\"color:#a6e22e\">T<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">b<\/span> <span style=\"color:#66d9ef\">extends<\/span> <span style=\"color:#66d9ef\">keyof<\/span> <span style=\"color:#a6e22e\">T<\/span>[<span style=\"color:#a6e22e\">a<\/span>],\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">c<\/span> <span style=\"color:#66d9ef\">extends<\/span> <span style=\"color:#66d9ef\">keyof<\/span> <span style=\"color:#a6e22e\">T<\/span>[<span style=\"color:#a6e22e\">a<\/span>][<span style=\"color:#a6e22e\">b<\/span>],\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">d<\/span> <span style=\"color:#66d9ef\">extends<\/span> <span style=\"color:#66d9ef\">keyof<\/span> <span style=\"color:#a6e22e\">T<\/span>[<span style=\"color:#a6e22e\">a<\/span>][<span style=\"color:#a6e22e\">b<\/span>][<span style=\"color:#a6e22e\">c<\/span>],\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">e<\/span> <span style=\"color:#66d9ef\">extends<\/span> <span style=\"color:#66d9ef\">keyof<\/span> <span style=\"color:#a6e22e\">T<\/span>[<span style=\"color:#a6e22e\">a<\/span>][<span style=\"color:#a6e22e\">b<\/span>][<span style=\"color:#a6e22e\">c<\/span>][<span style=\"color:#a6e22e\">d<\/span>]\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#f92672\">&gt;<\/span>(\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">key1<\/span>: <span style=\"color:#66d9ef\">a<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">key2<\/span>: <span style=\"color:#66d9ef\">b<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">key3<\/span>: <span style=\"color:#66d9ef\">c<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">key4<\/span>: <span style=\"color:#66d9ef\">d<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">key5<\/span>: <span style=\"color:#66d9ef\">e<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>)<span style=\"color:#f92672\">:<\/span> (<span style=\"color:#a6e22e\">source$<\/span>: <span style=\"color:#66d9ef\">Observable<\/span>&lt;<span style=\"color:#f92672\">T<\/span>&gt;) <span style=\"color:#f92672\">=&gt;<\/span> <span style=\"color:#a6e22e\">Observable<\/span>&lt;<span style=\"color:#f92672\">T<\/span><span style=\"color:#960050;background-color:#1e0010\">[<\/span><span style=\"color:#a6e22e\">a<\/span><span style=\"color:#960050;background-color:#1e0010\">][<\/span><span style=\"color:#a6e22e\">b<\/span><span style=\"color:#960050;background-color:#1e0010\">][<\/span><span style=\"color:#a6e22e\">c<\/span><span style=\"color:#960050;background-color:#1e0010\">][<\/span><span style=\"color:#a6e22e\">d<\/span><span style=\"color:#960050;background-color:#1e0010\">][<\/span><span style=\"color:#a6e22e\">e<\/span><span style=\"color:#960050;background-color:#1e0010\">]<\/span>&gt;;\n<\/span><\/span><\/code><\/pre><\/div><p>where <code>T<\/code> is the generic type parameter passed into <code>Store<\/code>: <code>export class Store&lt;T&gt; extends Observable&lt;T&gt;<\/code>. In this case, it&rsquo;s <code>AppState<\/code>. <code>foo<\/code> must be a key of <code>AppState<\/code>(the <code>T<\/code>), <code>fooUsers<\/code> must be a key of <code>AppState['foo']<\/code> and so forth&hellip;<\/p>\n<p>Under the hood the mapping is done with the help of the <code>pluck<\/code> operator, which provides a declarative way to select properties from objects:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">export<\/span> <span style=\"color:#66d9ef\">function<\/span> <span style=\"color:#a6e22e\">select<\/span>&lt;<span style=\"color:#f92672\">T<\/span><span style=\"color:#960050;background-color:#1e0010\">,<\/span> <span style=\"color:#a6e22e\">Props<\/span><span style=\"color:#960050;background-color:#1e0010\">,<\/span> <span style=\"color:#a6e22e\">K<\/span>&gt;(\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">pathOrMapFn<\/span><span style=\"color:#f92672\">:<\/span> ((<span style=\"color:#a6e22e\">state<\/span>: <span style=\"color:#66d9ef\">T<\/span>, <span style=\"color:#a6e22e\">props?<\/span>: <span style=\"color:#66d9ef\">Props<\/span>) <span style=\"color:#f92672\">=&gt;<\/span> <span style=\"color:#66d9ef\">any<\/span>) <span style=\"color:#f92672\">|<\/span> <span style=\"color:#66d9ef\">string<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">propsOrPath?<\/span>: <span style=\"color:#66d9ef\">Props<\/span> <span style=\"color:#f92672\">|<\/span> <span style=\"color:#66d9ef\">string<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  ...<span style=\"color:#a6e22e\">paths<\/span>: <span style=\"color:#66d9ef\">string<\/span>[]\n<\/span><\/span><span style=\"display:flex;\"><span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#66d9ef\">function<\/span> <span style=\"color:#a6e22e\">selectOperator<\/span>(<span style=\"color:#a6e22e\">source$<\/span>: <span style=\"color:#66d9ef\">Observable<\/span>&lt;<span style=\"color:#f92672\">T<\/span>&gt;)<span style=\"color:#f92672\">:<\/span> <span style=\"color:#a6e22e\">Observable<\/span>&lt;<span style=\"color:#f92672\">K<\/span>&gt; {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">let<\/span> <span style=\"color:#a6e22e\">mapped$<\/span>: <span style=\"color:#66d9ef\">Observable<\/span>&lt;<span style=\"color:#f92672\">any<\/span>&gt;;\n<\/span><\/span><span style=\"display:flex;\"><span>    \n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#66d9ef\">typeof<\/span> <span style=\"color:#a6e22e\">pathOrMapFn<\/span> <span style=\"color:#f92672\">===<\/span> <span style=\"color:#e6db74\">&#39;string&#39;<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">pathSlices<\/span> <span style=\"color:#f92672\">=<\/span> [&lt;<span style=\"color:#f92672\">string<\/span>&gt;<span style=\"color:#a6e22e\">propsOrPath<\/span>, ...<span style=\"color:#a6e22e\">paths<\/span>].<span style=\"color:#a6e22e\">filter<\/span>(Boolean);\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#a6e22e\">mapped$<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">source$<\/span>.<span style=\"color:#a6e22e\">pipe<\/span>(<span style=\"color:#a6e22e\">pluck<\/span>(<span style=\"color:#a6e22e\">pathOrMapFn<\/span>, ...<span style=\"color:#a6e22e\">pathSlices<\/span>));\n<\/span><\/span><span style=\"display:flex;\"><span>    } \n<\/span><\/span><span style=\"display:flex;\"><span>    \n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#75715e\">\/* ... *\/<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>  }\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><h4 id=\"provide-a-custom-operator-that-will-do-the-mapping\">\n  <span>\n  Provide a custom operator that will do the mapping\n  <\/span>\n  <a href=\"#provide-a-custom-operator-that-will-do-the-mapping\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h4><div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">export<\/span> <span style=\"color:#66d9ef\">function<\/span> <span style=\"color:#a6e22e\">select<\/span>&lt;<span style=\"color:#f92672\">T<\/span><span style=\"color:#960050;background-color:#1e0010\">,<\/span> <span style=\"color:#a6e22e\">Props<\/span><span style=\"color:#960050;background-color:#1e0010\">,<\/span> <span style=\"color:#a6e22e\">K<\/span>&gt;(\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">mapFn<\/span><span style=\"color:#f92672\">:<\/span> (<span style=\"color:#a6e22e\">state<\/span>: <span style=\"color:#66d9ef\">T<\/span>, <span style=\"color:#a6e22e\">props<\/span>: <span style=\"color:#66d9ef\">Props<\/span>) <span style=\"color:#f92672\">=&gt;<\/span> <span style=\"color:#a6e22e\">K<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">props?<\/span>: <span style=\"color:#66d9ef\">Props<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>)<span style=\"color:#f92672\">:<\/span> (<span style=\"color:#a6e22e\">source$<\/span>: <span style=\"color:#66d9ef\">Observable<\/span>&lt;<span style=\"color:#f92672\">T<\/span>&gt;) <span style=\"color:#f92672\">=&gt;<\/span> <span style=\"color:#a6e22e\">Observable<\/span>&lt;<span style=\"color:#f92672\">K<\/span>&gt;;\n<\/span><\/span><\/code><\/pre><\/div><p>This is similar to the previous approach, but instead of listing the properties, you provide a custom operator and optionally another argument(<code>props<\/code>). <code>props<\/code> may contain some data that is not part of the store and you can use it to alter the shape of the state.<\/p>\n<p>Another great benefit of this approach is that it can be used in conjunction with custom selectors, provided by the <code>createSelector()<\/code> function(you find more about <code>createSelector<\/code> in the following section).<\/p>\n<p><code>createSelector<\/code> will return a <code>MemoizedSelector<\/code>\/<code>MemoizedSelectorWithProps<\/code> which extends the base <code>Selector<\/code>.<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">export<\/span> <span style=\"color:#66d9ef\">function<\/span> <span style=\"color:#a6e22e\">createSelector<\/span>(\n<\/span><\/span><span style=\"display:flex;\"><span>  ...<span style=\"color:#a6e22e\">input<\/span>: <span style=\"color:#66d9ef\">any<\/span>[]\n<\/span><\/span><span style=\"display:flex;\"><span>)<span style=\"color:#f92672\">:<\/span> <span style=\"color:#a6e22e\">MemoizedSelector<\/span>&lt;<span style=\"color:#f92672\">any<\/span><span style=\"color:#960050;background-color:#1e0010\">,<\/span> <span style=\"color:#a6e22e\">any<\/span>&gt; <span style=\"color:#f92672\">|<\/span> <span style=\"color:#a6e22e\">MemoizedSelectorWithProps<\/span>&lt;<span style=\"color:#f92672\">any<\/span><span style=\"color:#960050;background-color:#1e0010\">,<\/span> <span style=\"color:#a6e22e\">any<\/span><span style=\"color:#960050;background-color:#1e0010\">,<\/span> <span style=\"color:#a6e22e\">any<\/span>&gt; { <span style=\"color:#75715e\">\/* ... *\/<\/span> }\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">export<\/span> <span style=\"color:#66d9ef\">interface<\/span> <span style=\"color:#a6e22e\">MemoizedSelector<\/span><span style=\"color:#f92672\">&lt;<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">State<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">Result<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">ProjectorFn<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">DefaultProjectorFn<\/span>&lt;<span style=\"color:#f92672\">Result<\/span>&gt;\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#f92672\">&gt;<\/span> <span style=\"color:#66d9ef\">extends<\/span> <span style=\"color:#a6e22e\">Selector<\/span>&lt;<span style=\"color:#f92672\">State<\/span><span style=\"color:#960050;background-color:#1e0010\">,<\/span> <span style=\"color:#a6e22e\">Result<\/span>&gt; {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">release<\/span>()<span style=\"color:#f92672\">:<\/span> <span style=\"color:#66d9ef\">void<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#75715e\">\/* ... *\/<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p>Put differently, it returns a selector(a function that accepts a state and returns something that depends on that state) or a selector with props(similar to a selector, but it can also receive some <code>props<\/code>).<br>\nThis is useful to know because when using a custom selector, the magic is achieved with the <code>map<\/code> operator:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">export<\/span> <span style=\"color:#66d9ef\">function<\/span> <span style=\"color:#a6e22e\">select<\/span>&lt;<span style=\"color:#f92672\">T<\/span><span style=\"color:#960050;background-color:#1e0010\">,<\/span> <span style=\"color:#a6e22e\">Props<\/span><span style=\"color:#960050;background-color:#1e0010\">,<\/span> <span style=\"color:#a6e22e\">K<\/span>&gt;(\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">pathOrMapFn<\/span><span style=\"color:#f92672\">:<\/span> ((<span style=\"color:#a6e22e\">state<\/span>: <span style=\"color:#66d9ef\">T<\/span>, <span style=\"color:#a6e22e\">props?<\/span>: <span style=\"color:#66d9ef\">Props<\/span>) <span style=\"color:#f92672\">=&gt;<\/span> <span style=\"color:#66d9ef\">any<\/span>) <span style=\"color:#f92672\">|<\/span> <span style=\"color:#66d9ef\">string<\/span>, <span style=\"color:#75715e\">\/\/ &lt;- Complies with `MemoizedSelector` | `MemoizedSelectorWithProps`\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>  <span style=\"color:#a6e22e\">propsOrPath?<\/span>: <span style=\"color:#66d9ef\">Props<\/span> <span style=\"color:#f92672\">|<\/span> <span style=\"color:#66d9ef\">string<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  ...<span style=\"color:#a6e22e\">paths<\/span>: <span style=\"color:#66d9ef\">string<\/span>[]\n<\/span><\/span><span style=\"display:flex;\"><span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#66d9ef\">function<\/span> <span style=\"color:#a6e22e\">selectOperator<\/span>(<span style=\"color:#a6e22e\">source$<\/span>: <span style=\"color:#66d9ef\">Observable<\/span>&lt;<span style=\"color:#f92672\">T<\/span>&gt;)<span style=\"color:#f92672\">:<\/span> <span style=\"color:#a6e22e\">Observable<\/span>&lt;<span style=\"color:#f92672\">K<\/span>&gt; {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">let<\/span> <span style=\"color:#a6e22e\">mapped$<\/span>: <span style=\"color:#66d9ef\">Observable<\/span>&lt;<span style=\"color:#f92672\">any<\/span>&gt;;\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#75715e\">\/* ... *\/<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#66d9ef\">typeof<\/span> <span style=\"color:#a6e22e\">pathOrMapFn<\/span> <span style=\"color:#f92672\">===<\/span> <span style=\"color:#e6db74\">&#39;function&#39;<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#a6e22e\">mapped$<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">source$<\/span>.<span style=\"color:#a6e22e\">pipe<\/span>(\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#a6e22e\">map<\/span>(<span style=\"color:#a6e22e\">source<\/span> <span style=\"color:#f92672\">=&gt;<\/span> <span style=\"color:#a6e22e\">pathOrMapFn<\/span>(<span style=\"color:#a6e22e\">source<\/span>, &lt;<span style=\"color:#f92672\">Props<\/span>&gt;<span style=\"color:#a6e22e\">propsOrPath<\/span>))\n<\/span><\/span><span style=\"display:flex;\"><span>      );\n<\/span><\/span><span style=\"display:flex;\"><span>    }\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#75715e\">\/* ... *\/<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>  };\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p>An example could look like this:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">export<\/span> <span style=\"color:#66d9ef\">function<\/span> <span style=\"color:#a6e22e\">select<\/span>&lt;<span style=\"color:#f92672\">T<\/span><span style=\"color:#960050;background-color:#1e0010\">,<\/span> <span style=\"color:#a6e22e\">Props<\/span><span style=\"color:#960050;background-color:#1e0010\">,<\/span> <span style=\"color:#a6e22e\">K<\/span>&gt;(\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">pathOrMapFn<\/span><span style=\"color:#f92672\">:<\/span> ((<span style=\"color:#a6e22e\">state<\/span>: <span style=\"color:#66d9ef\">T<\/span>, <span style=\"color:#a6e22e\">props?<\/span>: <span style=\"color:#66d9ef\">Props<\/span>) <span style=\"color:#f92672\">=&gt;<\/span> <span style=\"color:#66d9ef\">any<\/span>) <span style=\"color:#f92672\">|<\/span> <span style=\"color:#66d9ef\">string<\/span>, <span style=\"color:#75715e\">\/\/ &lt;- Complies with `MemoizedSelector` | `MemoizedSelectorWithProps`\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>  <span style=\"color:#a6e22e\">propsOrPath?<\/span>: <span style=\"color:#66d9ef\">Props<\/span> <span style=\"color:#f92672\">|<\/span> <span style=\"color:#66d9ef\">string<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  ...<span style=\"color:#a6e22e\">paths<\/span>: <span style=\"color:#66d9ef\">string<\/span>[]\n<\/span><\/span><span style=\"display:flex;\"><span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#66d9ef\">function<\/span> <span style=\"color:#a6e22e\">selectOperator<\/span>(<span style=\"color:#a6e22e\">source$<\/span>: <span style=\"color:#66d9ef\">Observable<\/span>&lt;<span style=\"color:#f92672\">T<\/span>&gt;)<span style=\"color:#f92672\">:<\/span> <span style=\"color:#a6e22e\">Observable<\/span>&lt;<span style=\"color:#f92672\">K<\/span>&gt; {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">let<\/span> <span style=\"color:#a6e22e\">mapped$<\/span>: <span style=\"color:#66d9ef\">Observable<\/span>&lt;<span style=\"color:#f92672\">any<\/span>&gt;;\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#75715e\">\/* ... *\/<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#66d9ef\">typeof<\/span> <span style=\"color:#a6e22e\">pathOrMapFn<\/span> <span style=\"color:#f92672\">===<\/span> <span style=\"color:#e6db74\">&#39;function&#39;<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#a6e22e\">mapped$<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">source$<\/span>.<span style=\"color:#a6e22e\">pipe<\/span>(\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#a6e22e\">map<\/span>(<span style=\"color:#a6e22e\">source<\/span> <span style=\"color:#f92672\">=&gt;<\/span> <span style=\"color:#a6e22e\">pathOrMapFn<\/span>(<span style=\"color:#a6e22e\">source<\/span>, &lt;<span style=\"color:#f92672\">Props<\/span>&gt;<span style=\"color:#a6e22e\">propsOrPath<\/span>))\n<\/span><\/span><span style=\"display:flex;\"><span>      );\n<\/span><\/span><span style=\"display:flex;\"><span>    }\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#75715e\">\/* ... *\/<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>  };\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><h4 id=\"use-custom-selectors\">\n  <span>\n  Use custom selectors\n  <\/span>\n  <a href=\"#use-custom-selectors\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h4><p>Sometimes you might want to have more control on the situation. In this case, we can use the <code>createSelector<\/code> function which can take a bunch of selectors and lastly, a projection function. The selectors will allow us to select certain slices from the store, whereas the last provided function will give the shape of the emitted value(i.e: the state object), based on the existing selectors. It will then project the value into the stream so the subscribers can consume it.<\/p>\n<p>This feature is strongly based on the power of pure functions. Because selectors must be pure functions, memoization can take place, which prevents us from redoing the same task multiple times if the same arguments are provided.<\/p>\n<p>A selector might look like this:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">export<\/span> <span style=\"color:#66d9ef\">type<\/span> <span style=\"color:#a6e22e\">Selector<\/span>&lt;<span style=\"color:#f92672\">T<\/span><span style=\"color:#960050;background-color:#1e0010\">,<\/span> <span style=\"color:#a6e22e\">V<\/span>&gt; <span style=\"color:#f92672\">=<\/span> (<span style=\"color:#a6e22e\">state<\/span>: <span style=\"color:#66d9ef\">T<\/span>) <span style=\"color:#f92672\">=&gt;<\/span> <span style=\"color:#a6e22e\">V<\/span>;\n<\/span><\/span><\/code><\/pre><\/div><p>or it might receive some <code>props<\/code> object that contains data which is not part of store, but might influence the final shape of the stream&rsquo;s values:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">export<\/span> <span style=\"color:#66d9ef\">type<\/span> <span style=\"color:#a6e22e\">SelectorWithProps<\/span>&lt;<span style=\"color:#f92672\">State<\/span><span style=\"color:#960050;background-color:#1e0010\">,<\/span> <span style=\"color:#a6e22e\">Props<\/span><span style=\"color:#960050;background-color:#1e0010\">,<\/span> <span style=\"color:#a6e22e\">Result<\/span>&gt; <span style=\"color:#f92672\">=<\/span> (\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">state<\/span>: <span style=\"color:#66d9ef\">State<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">props<\/span>: <span style=\"color:#66d9ef\">Props<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>) <span style=\"color:#f92672\">=&gt;<\/span> <span style=\"color:#a6e22e\">Result<\/span>;\n<\/span><\/span><\/code><\/pre><\/div><p>As you can notice, there is no hint that indicates that the above selector can be memoized.<\/p>\n<p>A memoized selector, which can be the result of <code>createSelector<\/code>, looks like this:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">export<\/span> <span style=\"color:#66d9ef\">interface<\/span> <span style=\"color:#a6e22e\">MemoizedSelector<\/span><span style=\"color:#f92672\">&lt;<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">State<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">Result<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">ProjectorFn<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">DefaultProjectorFn<\/span>&lt;<span style=\"color:#f92672\">Result<\/span>&gt;\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#f92672\">&gt;<\/span> <span style=\"color:#66d9ef\">extends<\/span> <span style=\"color:#a6e22e\">Selector<\/span>&lt;<span style=\"color:#f92672\">State<\/span><span style=\"color:#960050;background-color:#1e0010\">,<\/span> <span style=\"color:#a6e22e\">Result<\/span>&gt; {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">release<\/span>()<span style=\"color:#f92672\">:<\/span> <span style=\"color:#66d9ef\">void<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">projector<\/span>: <span style=\"color:#66d9ef\">ProjectorFn<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">setResult<\/span><span style=\"color:#f92672\">:<\/span> (<span style=\"color:#a6e22e\">result?<\/span>: <span style=\"color:#66d9ef\">Result<\/span>) <span style=\"color:#f92672\">=&gt;<\/span> <span style=\"color:#66d9ef\">void<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">clearResult<\/span><span style=\"color:#f92672\">:<\/span> () <span style=\"color:#f92672\">=&gt;<\/span> <span style=\"color:#66d9ef\">void<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">export<\/span> <span style=\"color:#66d9ef\">type<\/span> <span style=\"color:#a6e22e\">DefaultProjectorFn<\/span>&lt;<span style=\"color:#f92672\">T<\/span>&gt; <span style=\"color:#f92672\">=<\/span> (...<span style=\"color:#a6e22e\">args<\/span>: <span style=\"color:#66d9ef\">any<\/span>[]) <span style=\"color:#f92672\">=&gt;<\/span> <span style=\"color:#a6e22e\">T<\/span>;\n<\/span><\/span><\/code><\/pre><\/div><ul>\n<li>projector is just the projection function mentioned before, it computes the shape of the data based on the selectors<\/li>\n<li><code>release()<\/code> - release the memozied value from memory<\/li>\n<\/ul>\n<p>There is also <code>MemoizedSelectorWithProps&lt;State, Props, Result&gt;<\/code> which simply extends <code>SelectorWithProps<\/code>, but has the same methods as <code>MemoizedSelector<\/code>.<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">export<\/span> <span style=\"color:#66d9ef\">function<\/span> <span style=\"color:#a6e22e\">createSelector<\/span>(\n<\/span><\/span><span style=\"display:flex;\"><span>  ...<span style=\"color:#a6e22e\">input<\/span>: <span style=\"color:#66d9ef\">any<\/span>[]\n<\/span><\/span><span style=\"display:flex;\"><span>)<span style=\"color:#f92672\">:<\/span> <span style=\"color:#a6e22e\">MemoizedSelector<\/span>&lt;<span style=\"color:#f92672\">any<\/span><span style=\"color:#960050;background-color:#1e0010\">,<\/span> <span style=\"color:#a6e22e\">any<\/span>&gt; <span style=\"color:#f92672\">|<\/span> <span style=\"color:#a6e22e\">MemoizedSelectorWithProps<\/span>&lt;<span style=\"color:#f92672\">any<\/span><span style=\"color:#960050;background-color:#1e0010\">,<\/span> <span style=\"color:#a6e22e\">any<\/span><span style=\"color:#960050;background-color:#1e0010\">,<\/span> <span style=\"color:#a6e22e\">any<\/span>&gt; {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#a6e22e\">createSelectorFactory<\/span>(<span style=\"color:#a6e22e\">defaultMemoize<\/span>)(...<span style=\"color:#a6e22e\">input<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p><code>defaultMemoize<\/code> will take a projection function and will provide a way to memoize it:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">export<\/span> <span style=\"color:#66d9ef\">function<\/span> <span style=\"color:#a6e22e\">defaultMemoize<\/span>(\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">projectionFn<\/span>: <span style=\"color:#66d9ef\">AnyFn<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">isArgumentsEqual<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">isEqualCheck<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">isResultEqual<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">isEqualCheck<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>)<span style=\"color:#f92672\">:<\/span> <span style=\"color:#a6e22e\">MemoizedProjection<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">let<\/span> <span style=\"color:#a6e22e\">lastArguments<\/span>: <span style=\"color:#66d9ef\">null<\/span> <span style=\"color:#f92672\">|<\/span> <span style=\"color:#a6e22e\">IArguments<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">null<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">let<\/span> <span style=\"color:#a6e22e\">lastResult<\/span>: <span style=\"color:#66d9ef\">any<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">null<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">let<\/span> <span style=\"color:#a6e22e\">overrideResult<\/span>: <span style=\"color:#66d9ef\">any<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#75715e\">\/\/ Release value from memory \n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>  <span style=\"color:#66d9ef\">function<\/span> <span style=\"color:#a6e22e\">reset() {<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">lastArguments<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">null<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">lastResult<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">null<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>  }\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">function<\/span> <span style=\"color:#a6e22e\">setResult<\/span>(<span style=\"color:#a6e22e\">result<\/span>: <span style=\"color:#66d9ef\">any<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">undefined<\/span>) { <span style=\"color:#a6e22e\">overrideResult<\/span> <span style=\"color:#f92672\">=<\/span> { <span style=\"color:#a6e22e\">result<\/span> }; }\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">function<\/span> <span style=\"color:#a6e22e\">clearResult() {<\/span> <span style=\"color:#a6e22e\">overrideResult<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">undefined<\/span>; }\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">function<\/span> <span style=\"color:#a6e22e\">memoized<\/span>()<span style=\"color:#f92672\">:<\/span> <span style=\"color:#66d9ef\">any<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#a6e22e\">overrideResult<\/span> <span style=\"color:#f92672\">!==<\/span> <span style=\"color:#66d9ef\">undefined<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#a6e22e\">overrideResult<\/span>.<span style=\"color:#a6e22e\">result<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>    }\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#75715e\">\/\/ First time the function is invoked\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>    <span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#f92672\">!<\/span><span style=\"color:#a6e22e\">lastArguments<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#75715e\">\/\/ Call the projection function with the provided arguments\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>      <span style=\"color:#a6e22e\">lastResult<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">projectionFn<\/span>.<span style=\"color:#a6e22e\">apply<\/span>(<span style=\"color:#66d9ef\">null<\/span>, <span style=\"color:#a6e22e\">arguments<\/span> <span style=\"color:#66d9ef\">as<\/span> <span style=\"color:#66d9ef\">any<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#a6e22e\">lastArguments<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">arguments<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#a6e22e\">lastResult<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>    }\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#75715e\">\/\/ If the arguments are not different than the previous ones\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>    <span style=\"color:#75715e\">\/\/ there is no need to re-compute the results\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>    <span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#f92672\">!<\/span><span style=\"color:#a6e22e\">isArgumentsChanged<\/span>(<span style=\"color:#a6e22e\">arguments<\/span>, <span style=\"color:#a6e22e\">lastArguments<\/span>, <span style=\"color:#a6e22e\">isArgumentsEqual<\/span>)) {\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#a6e22e\">lastResult<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>    }\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#75715e\">\/\/ If we reached this point, it means the arguments were different\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>    <span style=\"color:#75715e\">\/\/ which requires a new computation of the result\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>    <span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">newResult<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">projectionFn<\/span>.<span style=\"color:#a6e22e\">apply<\/span>(<span style=\"color:#66d9ef\">null<\/span>, <span style=\"color:#a6e22e\">arguments<\/span> <span style=\"color:#66d9ef\">as<\/span> <span style=\"color:#66d9ef\">any<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">lastArguments<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">arguments<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#a6e22e\">isResultEqual<\/span>(<span style=\"color:#a6e22e\">lastResult<\/span>, <span style=\"color:#a6e22e\">newResult<\/span>)) {\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#a6e22e\">lastResult<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>    }\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">lastResult<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">newResult<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#a6e22e\">newResult<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>  }\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">return<\/span> { <span style=\"color:#a6e22e\">memoized<\/span>, <span style=\"color:#a6e22e\">reset<\/span>, <span style=\"color:#a6e22e\">setResult<\/span>, <span style=\"color:#a6e22e\">clearResult<\/span> };\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p>The memoization happens in the <code>memoized<\/code> function. It is deliberately declared as a function declaration in order to gain access to the <code>arguments<\/code> special variable. Arrow functions don&rsquo;t have it!<\/p>\n<p>Consider this example:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">function<\/span> <span style=\"color:#a6e22e\">isEqualCheck<\/span>(<span style=\"color:#a6e22e\">a<\/span>: <span style=\"color:#66d9ef\">any<\/span>, <span style=\"color:#a6e22e\">b<\/span>: <span style=\"color:#66d9ef\">any<\/span>)<span style=\"color:#f92672\">:<\/span> <span style=\"color:#66d9ef\">boolean<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#a6e22e\">a<\/span> <span style=\"color:#f92672\">===<\/span> <span style=\"color:#a6e22e\">b<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">function<\/span> <span style=\"color:#a6e22e\">sum<\/span> (<span style=\"color:#a6e22e\">a<\/span>, <span style=\"color:#a6e22e\">b<\/span>) { <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#a6e22e\">a<\/span> <span style=\"color:#f92672\">+<\/span> <span style=\"color:#a6e22e\">b<\/span>; };\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">memoizedSum<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">defaultMemoize<\/span>(<span style=\"color:#a6e22e\">sum<\/span>, <span style=\"color:#a6e22e\">isEqualCheck<\/span>, <span style=\"color:#a6e22e\">isEqualCheck<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/* \n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">  `sum` is executed\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">  if (!lastArguments) { \/\/ &lt;-- `lastArguments = null`\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">    \/\/ Call the projection function with the provided arguments\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">    lastResult = projectionFn.apply(null, arguments as any);\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">    lastArguments = arguments;\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">    return lastResult;\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">  }\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">*\/<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">memoizedSum<\/span>.<span style=\"color:#a6e22e\">memoized<\/span>(<span style=\"color:#ae81ff\">1<\/span>, <span style=\"color:#ae81ff\">3<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/*\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"> `sum` will not be executed again as it would be called with the same parameters\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"> if (!isArgumentsChanged(arguments, lastArguments, isArgumentsEqual)) {\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">    return lastResult;\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">  }\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">*\/<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">memoizedSum<\/span>.<span style=\"color:#a6e22e\">memoized<\/span>(<span style=\"color:#ae81ff\">1<\/span>, <span style=\"color:#ae81ff\">3<\/span>);\n<\/span><\/span><\/code><\/pre><\/div><p><code>defaultMemoize<\/code> is one of the building blocks of <code>createSelector<\/code> and it is where the memoization happens. However, when using <code>createSelector<\/code>, the memoization can occur in 2 places:<\/p>\n<ul>\n<li>at state level\u200a\u2014\u200awhen the selector receives the same state<\/li>\n<\/ul>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">incomingState<\/span> <span style=\"color:#f92672\">=<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">user<\/span><span style=\"color:#f92672\">:<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">hobbies<\/span><span style=\"color:#f92672\">:<\/span> [ {<span style=\"color:#a6e22e\">name<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;a&#39;<\/span>, <span style=\"color:#a6e22e\">recent<\/span>: <span style=\"color:#66d9ef\">true<\/span>}, { <span style=\"color:#a6e22e\">name<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;b&#39;<\/span>, <span style=\"color:#a6e22e\">recent<\/span>: <span style=\"color:#66d9ef\">false<\/span> } ],\n<\/span><\/span><span style=\"display:flex;\"><span>  },\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">otherProperty<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;foo&#39;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>};\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">userSelector<\/span> <span style=\"color:#f92672\">=<\/span> (<span style=\"color:#a6e22e\">s<\/span>: <span style=\"color:#66d9ef\">typeof<\/span> <span style=\"color:#a6e22e\">incomingState<\/span>) <span style=\"color:#f92672\">=&gt;<\/span> <span style=\"color:#a6e22e\">s<\/span>.<span style=\"color:#a6e22e\">user<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">userRecentHobbiesSelector<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">createSelector<\/span>(\n<\/span><\/span><span style=\"display:flex;\"><span>  (<span style=\"color:#a6e22e\">u<\/span>: <span style=\"color:#66d9ef\">typeof<\/span> <span style=\"color:#a6e22e\">incomingState<\/span>.<span style=\"color:#a6e22e\">user<\/span>) <span style=\"color:#f92672\">=&gt;<\/span> <span style=\"color:#a6e22e\">u<\/span>.<span style=\"color:#a6e22e\">hobbies<\/span>, <span style=\"color:#75715e\">\/\/ Selector\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>  <span style=\"color:#a6e22e\">hobbies<\/span> <span style=\"color:#f92672\">=&gt;<\/span> <span style=\"color:#a6e22e\">hobbies<\/span>.<span style=\"color:#a6e22e\">filter<\/span>(<span style=\"color:#a6e22e\">h<\/span> <span style=\"color:#f92672\">=&gt;<\/span> <span style=\"color:#a6e22e\">h<\/span>.<span style=\"color:#a6e22e\">recent<\/span>), <span style=\"color:#75715e\">\/\/ Projection Function\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ Similar to `this.store.pipe(select(\/* ... *\/))`\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span><span style=\"color:#a6e22e\">merge<\/span>(\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">of<\/span>(<span style=\"color:#a6e22e\">incomingState<\/span>),\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#75715e\">\/\/ Receiving an update sometime in the future\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>  <span style=\"color:#66d9ef\">of<\/span>({ ...<span style=\"color:#a6e22e\">incomingState<\/span>, <span style=\"color:#a6e22e\">otherProperty<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;bar&#39;<\/span> }).<span style=\"color:#a6e22e\">pipe<\/span>(<span style=\"color:#a6e22e\">delay<\/span>(<span style=\"color:#ae81ff\">500<\/span>))\n<\/span><\/span><span style=\"display:flex;\"><span>)\n<\/span><\/span><span style=\"display:flex;\"><span>  .<span style=\"color:#a6e22e\">pipe<\/span>(\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">pluck<\/span>(<span style=\"color:#e6db74\">&#39;user&#39;<\/span>),\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">select<\/span>(<span style=\"color:#a6e22e\">userRecentHobbiesSelector<\/span>),\n<\/span><\/span><span style=\"display:flex;\"><span>  )\n<\/span><\/span><span style=\"display:flex;\"><span>  .<span style=\"color:#a6e22e\">subscribe<\/span>(<span style=\"color:#a6e22e\">console<\/span>.<span style=\"color:#a6e22e\">log<\/span>)\n<\/span><\/span><\/code><\/pre><\/div><p>In the above example the log would be updated only once, because when the data comes the second time, <code>userRecentHobbiesSelector<\/code> would try to find out whether the new data is different than the previous one. If it&rsquo;s not, it&rsquo;s going to return the memoized value(the previous value). This also means that <code>userRecentHobbiesSelector<\/code>&rsquo;s projection function will be called only once.<\/p>\n<ul>\n<li>at projection function level\u200a\u2014\u200awhen the projection function is called with the same selectors.<\/li>\n<\/ul>\n<p>Even though the state object might have changed due to some other updates, it does not mean that some selectors\u2019 return values did as well.<\/p>\n<p>A selector created by <code>createSelector<\/code> can use the memoized value when updating a slice of the store that is not relevant for the projection function of that selector.<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">interface<\/span> <span style=\"color:#a6e22e\">User<\/span> { <span style=\"color:#a6e22e\">name<\/span>: <span style=\"color:#66d9ef\">string<\/span>; <span style=\"color:#a6e22e\">age<\/span>: <span style=\"color:#66d9ef\">number<\/span>; <span style=\"color:#a6e22e\">isOk<\/span>: <span style=\"color:#66d9ef\">boolean<\/span>; }\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">interface<\/span> <span style=\"color:#a6e22e\">State<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">users<\/span>: <span style=\"color:#66d9ef\">User<\/span>[];\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">shouldShow<\/span>: <span style=\"color:#66d9ef\">boolean<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">notRelevantProperty<\/span>: <span style=\"color:#66d9ef\">string<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">usersSelector<\/span> <span style=\"color:#f92672\">=<\/span> (<span style=\"color:#a6e22e\">s<\/span>: <span style=\"color:#66d9ef\">State<\/span>) <span style=\"color:#f92672\">=&gt;<\/span> <span style=\"color:#a6e22e\">s<\/span>.<span style=\"color:#a6e22e\">users<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">userProjectionFn<\/span> <span style=\"color:#f92672\">=<\/span> (<span style=\"color:#a6e22e\">users<\/span>: <span style=\"color:#66d9ef\">User<\/span>[]) <span style=\"color:#f92672\">=&gt;<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#a6e22e\">users<\/span>.<span style=\"color:#a6e22e\">filter<\/span>(<span style=\"color:#a6e22e\">u<\/span> <span style=\"color:#f92672\">=&gt;<\/span> <span style=\"color:#a6e22e\">u<\/span>.<span style=\"color:#a6e22e\">isOk<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>};\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">okUsersSelector<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">createSelector<\/span>(\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">usersSelector<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">userProjectionFn<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>);\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">let<\/span> <span style=\"color:#a6e22e\">dummyState<\/span>: <span style=\"color:#66d9ef\">State<\/span> <span style=\"color:#f92672\">=<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">shouldShow<\/span>: <span style=\"color:#66d9ef\">true<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">users<\/span><span style=\"color:#f92672\">:<\/span> [\n<\/span><\/span><span style=\"display:flex;\"><span>    { <span style=\"color:#a6e22e\">name<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;a&#39;<\/span>, <span style=\"color:#a6e22e\">age<\/span>: <span style=\"color:#66d9ef\">1<\/span>, <span style=\"color:#a6e22e\">isOk<\/span>: <span style=\"color:#66d9ef\">true<\/span> },\n<\/span><\/span><span style=\"display:flex;\"><span>    { <span style=\"color:#a6e22e\">name<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;b&#39;<\/span>, <span style=\"color:#a6e22e\">age<\/span>: <span style=\"color:#66d9ef\">2<\/span>, <span style=\"color:#a6e22e\">isOk<\/span>: <span style=\"color:#66d9ef\">false<\/span> },\n<\/span><\/span><span style=\"display:flex;\"><span>    { <span style=\"color:#a6e22e\">name<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;c&#39;<\/span>, <span style=\"color:#a6e22e\">age<\/span>: <span style=\"color:#66d9ef\">3<\/span>, <span style=\"color:#a6e22e\">isOk<\/span>: <span style=\"color:#66d9ef\">false<\/span> },\n<\/span><\/span><span style=\"display:flex;\"><span>    { <span style=\"color:#a6e22e\">name<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;d&#39;<\/span>, <span style=\"color:#a6e22e\">age<\/span>: <span style=\"color:#66d9ef\">4<\/span>, <span style=\"color:#a6e22e\">isOk<\/span>: <span style=\"color:#66d9ef\">true<\/span> },\n<\/span><\/span><span style=\"display:flex;\"><span>  ],\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">notRelevantProperty<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;not relevant&#39;<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>};\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ First time the selector is used with this state object\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ The returned value will be memoized\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span><span style=\"color:#a6e22e\">console<\/span>.<span style=\"color:#a6e22e\">log<\/span>(<span style=\"color:#a6e22e\">okUsersSelector<\/span>(<span style=\"color:#a6e22e\">dummyState<\/span>));\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ Although the `dummyState` object changed its reference\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ `dummyState.users` did not, meaning that `userProjectionFn` should use the memoized value\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ because `usersSelector` will return the same `users` object\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span><span style=\"color:#a6e22e\">dummyState<\/span> <span style=\"color:#f92672\">=<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>  ...<span style=\"color:#a6e22e\">dummyState<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">notRelevantProperty<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;not relevant - updated!&#39;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>};\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">console<\/span>.<span style=\"color:#a6e22e\">log<\/span>(<span style=\"color:#a6e22e\">okUsersSelector<\/span>(<span style=\"color:#a6e22e\">dummyState<\/span>));\n<\/span><\/span><\/code><\/pre><\/div><p>This happens because you\u2019d usually run more complex logic inside the projection function, whereas a selector should only return a property\u2019s value(a piece of the state), which is not an expensive operation.<\/p>\n<p>These features are brought together with the <code>createSelectorFactory<\/code>:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">export<\/span> <span style=\"color:#66d9ef\">function<\/span> <span style=\"color:#a6e22e\">createSelector<\/span>(\n<\/span><\/span><span style=\"display:flex;\"><span>  ...<span style=\"color:#a6e22e\">input<\/span>: <span style=\"color:#66d9ef\">any<\/span>[]\n<\/span><\/span><span style=\"display:flex;\"><span>)<span style=\"color:#f92672\">:<\/span> <span style=\"color:#a6e22e\">MemoizedSelector<\/span>&lt;<span style=\"color:#f92672\">any<\/span><span style=\"color:#960050;background-color:#1e0010\">,<\/span> <span style=\"color:#a6e22e\">any<\/span>&gt; <span style=\"color:#f92672\">|<\/span> <span style=\"color:#a6e22e\">MemoizedSelectorWithProps<\/span>&lt;<span style=\"color:#f92672\">any<\/span><span style=\"color:#960050;background-color:#1e0010\">,<\/span> <span style=\"color:#a6e22e\">any<\/span><span style=\"color:#960050;background-color:#1e0010\">,<\/span> <span style=\"color:#a6e22e\">any<\/span>&gt; {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#a6e22e\">createSelectorFactory<\/span>(<span style=\"color:#a6e22e\">defaultMemoize<\/span>)(...<span style=\"color:#a6e22e\">input<\/span>); <span style=\"color:#75715e\">\/\/ `input` - the sequence of selectors followed by the projection function\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>}\n<\/span><\/span><\/code><\/pre><\/div><div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">export<\/span> <span style=\"color:#66d9ef\">function<\/span> <span style=\"color:#a6e22e\">createSelectorFactory<\/span>(\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">memoize<\/span>: <span style=\"color:#66d9ef\">MemoizeFn<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">options<\/span>: <span style=\"color:#66d9ef\">SelectorFactoryConfig<\/span>&lt;<span style=\"color:#f92672\">any<\/span><span style=\"color:#960050;background-color:#1e0010\">,<\/span> <span style=\"color:#a6e22e\">any<\/span>&gt; <span style=\"color:#f92672\">=<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">stateFn<\/span>: <span style=\"color:#66d9ef\">defaultStateFn<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  }\n<\/span><\/span><span style=\"display:flex;\"><span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#66d9ef\">function<\/span>(\n<\/span><\/span><span style=\"display:flex;\"><span>    ...<span style=\"color:#a6e22e\">input<\/span>: <span style=\"color:#66d9ef\">any<\/span>[]\n<\/span><\/span><span style=\"display:flex;\"><span>  )<span style=\"color:#f92672\">:<\/span> <span style=\"color:#a6e22e\">MemoizedSelector<\/span>&lt;<span style=\"color:#f92672\">any<\/span><span style=\"color:#960050;background-color:#1e0010\">,<\/span> <span style=\"color:#a6e22e\">any<\/span>&gt; <span style=\"color:#f92672\">|<\/span> <span style=\"color:#a6e22e\">MemoizedSelectorWithProps<\/span>&lt;<span style=\"color:#f92672\">any<\/span><span style=\"color:#960050;background-color:#1e0010\">,<\/span> <span style=\"color:#a6e22e\">any<\/span><span style=\"color:#960050;background-color:#1e0010\">,<\/span> <span style=\"color:#a6e22e\">any<\/span>&gt; {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">let<\/span> <span style=\"color:#a6e22e\">args<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">input<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">if<\/span> (Array.<span style=\"color:#a6e22e\">isArray<\/span>(<span style=\"color:#a6e22e\">args<\/span>[<span style=\"color:#ae81ff\">0<\/span>])) {\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#66d9ef\">const<\/span> [<span style=\"color:#a6e22e\">head<\/span>, ...<span style=\"color:#a6e22e\">tail<\/span>] <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">args<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#a6e22e\">args<\/span> <span style=\"color:#f92672\">=<\/span> [...<span style=\"color:#a6e22e\">head<\/span>, ...<span style=\"color:#a6e22e\">tail<\/span>];\n<\/span><\/span><span style=\"display:flex;\"><span>    }\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">selectors<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">args<\/span>.<span style=\"color:#a6e22e\">slice<\/span>(<span style=\"color:#ae81ff\">0<\/span>, <span style=\"color:#a6e22e\">args<\/span>.<span style=\"color:#a6e22e\">length<\/span> <span style=\"color:#f92672\">-<\/span> <span style=\"color:#ae81ff\">1<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>    \n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#75715e\">\/\/ The projection function is always the last argument provided\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>    <span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">projector<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">args<\/span>[<span style=\"color:#a6e22e\">args<\/span>.<span style=\"color:#a6e22e\">length<\/span> <span style=\"color:#f92672\">-<\/span> <span style=\"color:#ae81ff\">1<\/span>];\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#75715e\">\/\/ `createSelector()` allows for composability\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>    <span style=\"color:#75715e\">\/\/ In `createSelector()` you can use selectors resulted from `createSelector()` as well\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>    <span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">memoizedSelectors<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">selectors<\/span>.<span style=\"color:#a6e22e\">filter<\/span>(\n<\/span><\/span><span style=\"display:flex;\"><span>      (<span style=\"color:#a6e22e\">selector<\/span>: <span style=\"color:#66d9ef\">any<\/span>) <span style=\"color:#f92672\">=&gt;<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#a6e22e\">selector<\/span>.<span style=\"color:#a6e22e\">release<\/span> <span style=\"color:#f92672\">&amp;&amp;<\/span> <span style=\"color:#66d9ef\">typeof<\/span> <span style=\"color:#a6e22e\">selector<\/span>.<span style=\"color:#a6e22e\">release<\/span> <span style=\"color:#f92672\">===<\/span> <span style=\"color:#e6db74\">&#39;function&#39;<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>    );\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#75715e\">\/\/ Memoizing the projector\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>    <span style=\"color:#75715e\">\/\/ If the selectors&#39;s return values are not different\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>    <span style=\"color:#75715e\">\/\/ There is no need to re-run the projector function\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>    <span style=\"color:#75715e\">\/\/ which might contain expensive logic\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>    <span style=\"color:#75715e\">\/\/ In this case, `memoize === `defaultMemoize`\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>    <span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">memoizedProjector<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">memoize<\/span>(<span style=\"color:#66d9ef\">function<\/span>(...<span style=\"color:#a6e22e\">selectors<\/span>: <span style=\"color:#66d9ef\">any<\/span>[]) {\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#a6e22e\">projector<\/span>.<span style=\"color:#a6e22e\">apply<\/span>(<span style=\"color:#66d9ef\">null<\/span>, <span style=\"color:#a6e22e\">selectors<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>    });\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">memoizedState<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">defaultMemoize<\/span>(<span style=\"color:#66d9ef\">function<\/span>(<span style=\"color:#a6e22e\">state<\/span>: <span style=\"color:#66d9ef\">any<\/span>, <span style=\"color:#a6e22e\">props<\/span>: <span style=\"color:#66d9ef\">any<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#a6e22e\">options<\/span>.<span style=\"color:#a6e22e\">stateFn<\/span>.<span style=\"color:#a6e22e\">apply<\/span>(<span style=\"color:#66d9ef\">null<\/span>, [\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#a6e22e\">state<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#a6e22e\">selectors<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#a6e22e\">props<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#a6e22e\">memoizedProjector<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>      ]);\n<\/span><\/span><span style=\"display:flex;\"><span>    });\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#75715e\">\/\/ Releasing the value from memory\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>    <span style=\"color:#66d9ef\">function<\/span> <span style=\"color:#a6e22e\">release() {<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#a6e22e\">memoizedState<\/span>.<span style=\"color:#a6e22e\">reset<\/span>();\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#a6e22e\">memoizedProjector<\/span>.<span style=\"color:#a6e22e\">reset<\/span>();\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#75715e\">\/\/ Releasing the selectors that were created by `createSelector()`\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>      <span style=\"color:#a6e22e\">memoizedSelectors<\/span>.<span style=\"color:#a6e22e\">forEach<\/span>(<span style=\"color:#a6e22e\">selector<\/span> <span style=\"color:#f92672\">=&gt;<\/span> <span style=\"color:#a6e22e\">selector<\/span>.<span style=\"color:#a6e22e\">release<\/span>());\n<\/span><\/span><span style=\"display:flex;\"><span>    }\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">return<\/span> Object.<span style=\"color:#a6e22e\">assign<\/span>(<span style=\"color:#a6e22e\">memoizedState<\/span>.<span style=\"color:#a6e22e\">memoized<\/span>, {\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#a6e22e\">release<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#a6e22e\">projector<\/span>: <span style=\"color:#66d9ef\">memoizedProjector.memoized<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#a6e22e\">setResult<\/span>: <span style=\"color:#66d9ef\">memoizedState.setResult<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#a6e22e\">clearResult<\/span>: <span style=\"color:#66d9ef\">memoizedState.clearResult<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>    });\n<\/span><\/span><span style=\"display:flex;\"><span>  };\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p><code>options.stateFn<\/code> maps to <code>defaultStateFn<\/code><\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#a6e22e\">props<\/span> <span style=\"color:#f92672\">===<\/span> <span style=\"color:#66d9ef\">undefined<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">args<\/span> <span style=\"color:#f92672\">=<\/span> (&lt;<span style=\"color:#f92672\">Selector<\/span><span style=\"color:#960050;background-color:#1e0010\">&lt;<\/span><span style=\"color:#a6e22e\">any<\/span><span style=\"color:#960050;background-color:#1e0010\">,<\/span> <span style=\"color:#a6e22e\">any<\/span>&gt;[]<span style=\"color:#f92672\">&gt;<\/span><span style=\"color:#a6e22e\">selectors<\/span>).<span style=\"color:#a6e22e\">map<\/span>(<span style=\"color:#a6e22e\">fn<\/span> <span style=\"color:#f92672\">=&gt;<\/span> <span style=\"color:#a6e22e\">fn<\/span>(<span style=\"color:#a6e22e\">state<\/span>));\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#a6e22e\">memoizedProjector<\/span>.<span style=\"color:#a6e22e\">memoized<\/span>.<span style=\"color:#a6e22e\">apply<\/span>(<span style=\"color:#66d9ef\">null<\/span>, <span style=\"color:#a6e22e\">args<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ `props` - available in each provided selector as the second argument\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span><span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">args<\/span> <span style=\"color:#f92672\">=<\/span> (&lt;<span style=\"color:#f92672\">SelectorWithProps<\/span><span style=\"color:#960050;background-color:#1e0010\">&lt;<\/span><span style=\"color:#a6e22e\">any<\/span><span style=\"color:#960050;background-color:#1e0010\">,<\/span> <span style=\"color:#a6e22e\">any<\/span><span style=\"color:#960050;background-color:#1e0010\">,<\/span> <span style=\"color:#a6e22e\">any<\/span>&gt;[]<span style=\"color:#f92672\">&gt;<\/span><span style=\"color:#a6e22e\">selectors<\/span>).<span style=\"color:#a6e22e\">map<\/span>(<span style=\"color:#a6e22e\">fn<\/span> <span style=\"color:#f92672\">=&gt;<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">fn<\/span>(<span style=\"color:#a6e22e\">state<\/span>, <span style=\"color:#a6e22e\">props<\/span>)\n<\/span><\/span><span style=\"display:flex;\"><span>);\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ `props` - available in the projector as well\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span><span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#a6e22e\">memoizedProjector<\/span>.<span style=\"color:#a6e22e\">memoized<\/span>.<span style=\"color:#a6e22e\">apply<\/span>(<span style=\"color:#66d9ef\">null<\/span>, [...<span style=\"color:#a6e22e\">args<\/span>, <span style=\"color:#a6e22e\">props<\/span>]);\n<\/span><\/span><\/code><\/pre><\/div><p>which is where the selectors are invoked. <code>memoizedProjector.memoized<\/code> will make sure that if the arguments(selectors&rsquo; return values) are not different than the previous ones, it will not call the projector again and will return the memoized value.<br>\nAlso, from the above snippets we can tell that the function returned from <code>createSelector()<\/code> and be called with 2 arguments: <code>state<\/code> and <code>props<\/code>, where <code>props<\/code> could be any data which does not necessarily belong to the store, but can influence the shape of the projector&rsquo;s output.<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">incomingState<\/span> <span style=\"color:#f92672\">=<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">user<\/span><span style=\"color:#f92672\">:<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">hobbies<\/span><span style=\"color:#f92672\">:<\/span> [ {<span style=\"color:#a6e22e\">name<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;a&#39;<\/span>, <span style=\"color:#a6e22e\">recent<\/span>: <span style=\"color:#66d9ef\">true<\/span>}, { <span style=\"color:#a6e22e\">name<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;b&#39;<\/span>, <span style=\"color:#a6e22e\">recent<\/span>: <span style=\"color:#66d9ef\">false<\/span> } ],\n<\/span><\/span><span style=\"display:flex;\"><span>  },\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">otherProperty<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;foo&#39;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>};\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">userSelector<\/span> <span style=\"color:#f92672\">=<\/span> (<span style=\"color:#a6e22e\">s<\/span>: <span style=\"color:#66d9ef\">typeof<\/span> <span style=\"color:#a6e22e\">incomingState<\/span>) <span style=\"color:#f92672\">=&gt;<\/span> <span style=\"color:#a6e22e\">s<\/span>.<span style=\"color:#a6e22e\">user<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">userRecentHobbiesSelector<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">createSelector<\/span>(\n<\/span><\/span><span style=\"display:flex;\"><span>  (<span style=\"color:#a6e22e\">u<\/span>: <span style=\"color:#66d9ef\">typeof<\/span> <span style=\"color:#a6e22e\">incomingState<\/span>.<span style=\"color:#a6e22e\">user<\/span>, <span style=\"color:#a6e22e\">props<\/span>) <span style=\"color:#f92672\">=&gt;<\/span> (<span style=\"color:#a6e22e\">console<\/span>.<span style=\"color:#a6e22e\">log<\/span>(<span style=\"color:#e6db74\">&#39;props&#39;<\/span>, <span style=\"color:#a6e22e\">props<\/span>),<span style=\"color:#a6e22e\">u<\/span>.<span style=\"color:#a6e22e\">hobbies<\/span>),\n<\/span><\/span><span style=\"display:flex;\"><span>  (<span style=\"color:#a6e22e\">hobbies<\/span>, <span style=\"color:#a6e22e\">props<\/span>) <span style=\"color:#f92672\">=&gt;<\/span> <span style=\"color:#a6e22e\">hobbies<\/span>.<span style=\"color:#a6e22e\">filter<\/span>(<span style=\"color:#a6e22e\">h<\/span> <span style=\"color:#f92672\">=&gt;<\/span> <span style=\"color:#a6e22e\">h<\/span>.<span style=\"color:#a6e22e\">recent<\/span>).<span style=\"color:#a6e22e\">map<\/span>(<span style=\"color:#a6e22e\">h<\/span> <span style=\"color:#f92672\">=&gt;<\/span> <span style=\"color:#e6db74\">`<\/span><span style=\"color:#e6db74\">${<\/span><span style=\"color:#a6e22e\">props<\/span>.<span style=\"color:#a6e22e\">prefix<\/span><span style=\"color:#e6db74\">}${<\/span><span style=\"color:#a6e22e\">h<\/span>.<span style=\"color:#a6e22e\">name<\/span><span style=\"color:#e6db74\">}${<\/span><span style=\"color:#a6e22e\">props<\/span>.<span style=\"color:#a6e22e\">suffix<\/span><span style=\"color:#e6db74\">}<\/span><span style=\"color:#e6db74\">`<\/span>),\n<\/span><\/span><span style=\"display:flex;\"><span>);\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">props<\/span> <span style=\"color:#f92672\">=<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">prefix<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;@@@@@&#39;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">suffix<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;______&#39;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>};\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">merge<\/span>(\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">of<\/span>(<span style=\"color:#a6e22e\">incomingState<\/span>),\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">of<\/span>({ ...<span style=\"color:#a6e22e\">incomingState<\/span>, <span style=\"color:#a6e22e\">otherProperty<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;bar&#39;<\/span> }).<span style=\"color:#a6e22e\">pipe<\/span>(<span style=\"color:#a6e22e\">delay<\/span>(<span style=\"color:#ae81ff\">500<\/span>))\n<\/span><\/span><span style=\"display:flex;\"><span>)\n<\/span><\/span><span style=\"display:flex;\"><span>  .<span style=\"color:#a6e22e\">pipe<\/span>(\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">pluck<\/span>(<span style=\"color:#e6db74\">&#39;user&#39;<\/span>),\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">select<\/span>(<span style=\"color:#a6e22e\">userRecentHobbiesSelector<\/span>, <span style=\"color:#a6e22e\">props<\/span>),\n<\/span><\/span><span style=\"display:flex;\"><span>  )\n<\/span><\/span><span style=\"display:flex;\"><span>  .<span style=\"color:#a6e22e\">subscribe<\/span>(<span style=\"color:#a6e22e\">console<\/span>.<span style=\"color:#a6e22e\">log<\/span>)\n<\/span><\/span><\/code><\/pre><\/div><p>We can tell from the above 2 snippets that <code>props<\/code> are available both in selectors and projection function.<\/p>\n<p><code>select<\/code> is the same function that is used in <code>Store.select<\/code>:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/* ... Inside `select` ... *\/<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#66d9ef\">typeof<\/span> <span style=\"color:#a6e22e\">pathOrMapFn<\/span> <span style=\"color:#f92672\">===<\/span> <span style=\"color:#e6db74\">&#39;string&#39;<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">pathSlices<\/span> <span style=\"color:#f92672\">=<\/span> [&lt;<span style=\"color:#f92672\">string<\/span>&gt;<span style=\"color:#a6e22e\">propsOrPath<\/span>, ...<span style=\"color:#a6e22e\">paths<\/span>].<span style=\"color:#a6e22e\">filter<\/span>(Boolean);\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">mapped$<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">source$<\/span>.<span style=\"color:#a6e22e\">pipe<\/span>(<span style=\"color:#a6e22e\">pluck<\/span>(<span style=\"color:#a6e22e\">pathOrMapFn<\/span>, ...<span style=\"color:#a6e22e\">pathSlices<\/span>));\n<\/span><\/span><span style=\"display:flex;\"><span>} <span style=\"color:#66d9ef\">else<\/span> <span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#66d9ef\">typeof<\/span> <span style=\"color:#a6e22e\">pathOrMapFn<\/span> <span style=\"color:#f92672\">===<\/span> <span style=\"color:#e6db74\">&#39;function&#39;<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">mapped$<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">source$<\/span>.<span style=\"color:#a6e22e\">pipe<\/span>(\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">map<\/span>(<span style=\"color:#a6e22e\">source<\/span> <span style=\"color:#f92672\">=&gt;<\/span> <span style=\"color:#a6e22e\">pathOrMapFn<\/span>(<span style=\"color:#a6e22e\">source<\/span>, &lt;<span style=\"color:#f92672\">Props<\/span>&gt;<span style=\"color:#a6e22e\">propsOrPath<\/span>))\n<\/span><\/span><span style=\"display:flex;\"><span>  );\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><h2 id=\"how-does-the-memoization-actually-work\">\n  <span>\n  How does the memoization actually work?\n  <\/span>\n  <a href=\"#how-does-the-memoization-actually-work\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><p>In order to get a better understanding of how this process works, let\u2019s have a look at its foundation:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ createSelectorFactory&#39;s returned function body: createSelector(...inputs) { return createSelectorFactory(defaultMemoize)(...input); }\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">let<\/span> <span style=\"color:#a6e22e\">args<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">input<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">selectors<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">args<\/span>.<span style=\"color:#a6e22e\">slice<\/span>(<span style=\"color:#ae81ff\">0<\/span>, <span style=\"color:#a6e22e\">args<\/span>.<span style=\"color:#a6e22e\">length<\/span> <span style=\"color:#f92672\">-<\/span> <span style=\"color:#ae81ff\">1<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">projector<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">args<\/span>[<span style=\"color:#a6e22e\">args<\/span>.<span style=\"color:#a6e22e\">length<\/span> <span style=\"color:#f92672\">-<\/span> <span style=\"color:#ae81ff\">1<\/span>];\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">memoizedSelectors<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">selectors<\/span>.<span style=\"color:#a6e22e\">filter<\/span>(\n<\/span><\/span><span style=\"display:flex;\"><span>  (<span style=\"color:#a6e22e\">selector<\/span>: <span style=\"color:#66d9ef\">any<\/span>) <span style=\"color:#f92672\">=&gt;<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">selector<\/span>.<span style=\"color:#a6e22e\">release<\/span> <span style=\"color:#f92672\">&amp;&amp;<\/span> <span style=\"color:#66d9ef\">typeof<\/span> <span style=\"color:#a6e22e\">selector<\/span>.<span style=\"color:#a6e22e\">release<\/span> <span style=\"color:#f92672\">===<\/span> <span style=\"color:#e6db74\">&#39;function&#39;<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>);\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ By default, `memoize === defaultMemoize`\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span><span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">memoizedProjector<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">memoize<\/span>(<span style=\"color:#66d9ef\">function<\/span>(...<span style=\"color:#a6e22e\">selectors<\/span>: <span style=\"color:#66d9ef\">any<\/span>[]) {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#a6e22e\">projector<\/span>.<span style=\"color:#a6e22e\">apply<\/span>(<span style=\"color:#66d9ef\">null<\/span>, <span style=\"color:#a6e22e\">selectors<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>});\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">memoizedState<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">defaultMemoize<\/span>(<span style=\"color:#66d9ef\">function<\/span>(<span style=\"color:#a6e22e\">state<\/span>: <span style=\"color:#66d9ef\">any<\/span>, <span style=\"color:#a6e22e\">props<\/span>: <span style=\"color:#66d9ef\">any<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#a6e22e\">options<\/span>.<span style=\"color:#a6e22e\">stateFn<\/span>.<span style=\"color:#a6e22e\">apply<\/span>(<span style=\"color:#66d9ef\">null<\/span>, [\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">state<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">selectors<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">props<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">memoizedProjector<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  ]);\n<\/span><\/span><span style=\"display:flex;\"><span>});\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">function<\/span> <span style=\"color:#a6e22e\">release() {<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">memoizedState<\/span>.<span style=\"color:#a6e22e\">reset<\/span>();\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">memoizedProjector<\/span>.<span style=\"color:#a6e22e\">reset<\/span>();\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">memoizedSelectors<\/span>.<span style=\"color:#a6e22e\">forEach<\/span>(<span style=\"color:#a6e22e\">selector<\/span> <span style=\"color:#f92672\">=&gt;<\/span> <span style=\"color:#a6e22e\">selector<\/span>.<span style=\"color:#a6e22e\">release<\/span>());\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">return<\/span> Object.<span style=\"color:#a6e22e\">assign<\/span>(<span style=\"color:#a6e22e\">memoizedState<\/span>.<span style=\"color:#a6e22e\">memoized<\/span>, {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">release<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">projector<\/span>: <span style=\"color:#66d9ef\">memoizedProjector.memoized<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">setResult<\/span>: <span style=\"color:#66d9ef\">memoizedState.setResult<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">clearResult<\/span>: <span style=\"color:#66d9ef\">memoizedState.clearResult<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>});\n<\/span><\/span><\/code><\/pre><\/div><p>It will return a function(<code>memoizedState.memoized<\/code>) that can be called with 2 arguments: <code>state<\/code> and <code>props<\/code>. <code>memoizedState.memoized<\/code> is the result of <code>createSelector()<\/code>.<\/p>\n<p>Whenever <code>memoizedState.memoized<\/code> is called, it will verify if there is any difference between the current function&rsquo;s arguments and previous ones. If that&rsquo;s the case, it will call the callback function provided to <code>defaultMemoize<\/code>:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">export<\/span> <span style=\"color:#66d9ef\">function<\/span> <span style=\"color:#a6e22e\">defaultMemoize<\/span>(<span style=\"color:#a6e22e\">projectionFn<\/span>: <span style=\"color:#66d9ef\">AnyFn<\/span>, <span style=\"color:#75715e\">\/* ... *\/<\/span>)<span style=\"color:#f92672\">:<\/span> <span style=\"color:#a6e22e\">MemoizedProjection<\/span> { <span style=\"color:#75715e\">\/* ... *\/<\/span> }\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">export<\/span> <span style=\"color:#66d9ef\">type<\/span> <span style=\"color:#a6e22e\">MemoizedProjection<\/span> <span style=\"color:#f92672\">=<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">memoized<\/span>: <span style=\"color:#66d9ef\">AnyFn<\/span>; <span style=\"color:#75715e\">\/\/ &lt;-- Here is where the memoization happens\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>  <span style=\"color:#a6e22e\">reset<\/span><span style=\"color:#f92672\">:<\/span> () <span style=\"color:#f92672\">=&gt;<\/span> <span style=\"color:#66d9ef\">void<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">setResult<\/span><span style=\"color:#f92672\">:<\/span> (<span style=\"color:#a6e22e\">result?<\/span>: <span style=\"color:#66d9ef\">any<\/span>) <span style=\"color:#f92672\">=&gt;<\/span> <span style=\"color:#66d9ef\">void<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">clearResult<\/span><span style=\"color:#f92672\">:<\/span> () <span style=\"color:#f92672\">=&gt;<\/span> <span style=\"color:#66d9ef\">void<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>};\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">function<\/span> <span style=\"color:#a6e22e\">memoized<\/span>()<span style=\"color:#f92672\">:<\/span> <span style=\"color:#66d9ef\">any<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#a6e22e\">overrideResult<\/span> <span style=\"color:#f92672\">!==<\/span> <span style=\"color:#66d9ef\">undefined<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#a6e22e\">overrideResult<\/span>.<span style=\"color:#a6e22e\">result<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>  }\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#f92672\">!<\/span><span style=\"color:#a6e22e\">lastArguments<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">lastResult<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">projectionFn<\/span>.<span style=\"color:#a6e22e\">apply<\/span>(<span style=\"color:#66d9ef\">null<\/span>, <span style=\"color:#a6e22e\">arguments<\/span> <span style=\"color:#66d9ef\">as<\/span> <span style=\"color:#66d9ef\">any<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">lastArguments<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">arguments<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#a6e22e\">lastResult<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>  }\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#f92672\">!<\/span><span style=\"color:#a6e22e\">isArgumentsChanged<\/span>(<span style=\"color:#a6e22e\">arguments<\/span>, <span style=\"color:#a6e22e\">lastArguments<\/span>, <span style=\"color:#a6e22e\">isArgumentsEqual<\/span>)) {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#a6e22e\">lastResult<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>  }\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">newResult<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">projectionFn<\/span>.<span style=\"color:#a6e22e\">apply<\/span>(<span style=\"color:#66d9ef\">null<\/span>, <span style=\"color:#a6e22e\">arguments<\/span> <span style=\"color:#66d9ef\">as<\/span> <span style=\"color:#66d9ef\">any<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">lastArguments<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">arguments<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#a6e22e\">isResultEqual<\/span>(<span style=\"color:#a6e22e\">lastResult<\/span>, <span style=\"color:#a6e22e\">newResult<\/span>)) {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#a6e22e\">lastResult<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>  }\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">lastResult<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">newResult<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#a6e22e\">newResult<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p>The <code>projectionFn<\/code> for <code>memoizedState<\/code> is:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ #1\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span><span style=\"color:#66d9ef\">function<\/span>(<span style=\"color:#a6e22e\">state<\/span>: <span style=\"color:#66d9ef\">any<\/span>, <span style=\"color:#a6e22e\">props<\/span>: <span style=\"color:#66d9ef\">any<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#a6e22e\">options<\/span>.<span style=\"color:#a6e22e\">stateFn<\/span>.<span style=\"color:#a6e22e\">apply<\/span>(<span style=\"color:#66d9ef\">null<\/span>, [\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">state<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">selectors<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">props<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">memoizedProjector<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  ]);\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p>whereas for <code>memoizedProject<\/code> is:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ #2\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span><span style=\"color:#66d9ef\">function<\/span>(...<span style=\"color:#a6e22e\">selectors<\/span>: <span style=\"color:#66d9ef\">any<\/span>[]) {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#a6e22e\">projector<\/span>.<span style=\"color:#a6e22e\">apply<\/span>(<span style=\"color:#66d9ef\">null<\/span>, <span style=\"color:#a6e22e\">selectors<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p>Consider this example:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">state<\/span> <span style=\"color:#f92672\">=<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">status<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;ok&#39;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">actions<\/span><span style=\"color:#f92672\">:<\/span> [ {<span style=\"color:#a6e22e\">name<\/span><span style=\"color:#f92672\">:<\/span><span style=\"color:#e6db74\">&#39;a1&#39;<\/span>, <span style=\"color:#a6e22e\">status<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;ok&#39;<\/span>}, {<span style=\"color:#a6e22e\">name<\/span><span style=\"color:#f92672\">:<\/span><span style=\"color:#e6db74\">&#39;a2&#39;<\/span>, <span style=\"color:#a6e22e\">status<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;denied&#39;<\/span>} ],\n<\/span><\/span><span style=\"display:flex;\"><span>};\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">actionsOfCrtStatusSelector<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">createSelector<\/span>(\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">s<\/span> <span style=\"color:#f92672\">=&gt;<\/span> <span style=\"color:#a6e22e\">s<\/span>.<span style=\"color:#a6e22e\">status<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">s<\/span> <span style=\"color:#f92672\">=&gt;<\/span> <span style=\"color:#a6e22e\">s<\/span>.<span style=\"color:#a6e22e\">actions<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  (<span style=\"color:#a6e22e\">status<\/span>, <span style=\"color:#a6e22e\">actions<\/span>) <span style=\"color:#f92672\">=&gt;<\/span> <span style=\"color:#a6e22e\">actions<\/span>.<span style=\"color:#a6e22e\">filter<\/span>(<span style=\"color:#a6e22e\">a<\/span> <span style=\"color:#f92672\">=&gt;<\/span> <span style=\"color:#a6e22e\">a<\/span>.<span style=\"color:#a6e22e\">status<\/span> <span style=\"color:#f92672\">===<\/span> <span style=\"color:#a6e22e\">status<\/span>),\n<\/span><\/span><span style=\"display:flex;\"><span>);\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ `actionsOfCrtStatusSelector` = `memoizedState.memoized`\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span><span style=\"color:#a6e22e\">actionsOfCrtStatusSelector<\/span>(<span style=\"color:#a6e22e\">state<\/span>);\n<\/span><\/span><\/code><\/pre><\/div><p>Here\u2019s what happens after the selector is called with a <code>state<\/code>:<\/p>\n<ul>\n<li><code>actionsOfCrtStatusSelector(state)<\/code> equals to <code>memoizedState.memoized(state)<\/code><\/li>\n<li><code>memoizedState.memoized<\/code> will check if the <code>state<\/code> argument is different than the previous one, but since it&rsquo;s the first call, these lines of <code>memoized<\/code> will be reached:<\/li>\n<\/ul>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#f92672\">!<\/span><span style=\"color:#a6e22e\">lastArguments<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#75715e\">\/\/ Call the function and memoize its result\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>  <span style=\"color:#a6e22e\">lastResult<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">projectionFn<\/span>.<span style=\"color:#a6e22e\">apply<\/span>(<span style=\"color:#66d9ef\">null<\/span>, <span style=\"color:#a6e22e\">arguments<\/span> <span style=\"color:#66d9ef\">as<\/span> <span style=\"color:#66d9ef\">any<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">lastArguments<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">arguments<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#a6e22e\">lastResult<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p>where <code>projectionFn<\/code> is <code>#1<\/code>(from above). \u00a0When invoked, it will call <code>options.stateFn<\/code> which looks like this:<\/p>\n<p>it is where all the selectors are invoked:<\/p>\n<ul>\n<li><code>memoizedProjector.memoized<\/code> will be called with the selectors&rsquo; results(and optionally a <code>props<\/code> object). since it is the first time <code>memoizedProjector.memoized<\/code> is invoked, it will call its projection function(<code>#2<\/code>):<\/li>\n<\/ul>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#f92672\">!<\/span><span style=\"color:#a6e22e\">lastArguments<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#75715e\">\/\/ Call the function and memoize its result\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>  <span style=\"color:#a6e22e\">lastResult<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">projectionFn<\/span>.<span style=\"color:#a6e22e\">apply<\/span>(<span style=\"color:#66d9ef\">null<\/span>, <span style=\"color:#a6e22e\">arguments<\/span> <span style=\"color:#66d9ef\">as<\/span> <span style=\"color:#66d9ef\">any<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">lastArguments<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">arguments<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#a6e22e\">lastResult<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ `projectionFn` from above\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span><span style=\"color:#66d9ef\">function<\/span>(...<span style=\"color:#a6e22e\">selectors<\/span>: <span style=\"color:#66d9ef\">any<\/span>[]) {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#a6e22e\">projector<\/span>.<span style=\"color:#a6e22e\">apply<\/span>(<span style=\"color:#66d9ef\">null<\/span>, <span style=\"color:#a6e22e\">selectors<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ `projector`\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>(<span style=\"color:#a6e22e\">status<\/span>, <span style=\"color:#a6e22e\">actions<\/span>) <span style=\"color:#f92672\">=&gt;<\/span> <span style=\"color:#a6e22e\">actions<\/span>.<span style=\"color:#a6e22e\">filter<\/span>(<span style=\"color:#a6e22e\">a<\/span> <span style=\"color:#f92672\">=&gt;<\/span> <span style=\"color:#a6e22e\">a<\/span>.<span style=\"color:#a6e22e\">status<\/span> <span style=\"color:#f92672\">===<\/span> <span style=\"color:#a6e22e\">status<\/span>),\n<\/span><\/span><\/code><\/pre><\/div><p><em>Note: even though arrow functions do not have<\/em> <code>_this_<\/code> <em>nor<\/em> <code>_arguments_<\/code> <em>available,<\/em> <code>_call()_<\/code><em>,<\/em> <code>_bind()_<\/code><em>,<\/em> <code>_apply()_<\/code> <em>can be used to pass arguments.<\/em><\/p>\n<p>The flow, in this case, would look as follows:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">memoizedProjector<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">memoize<\/span>(<span style=\"color:#75715e\">\/* #2 *\/<\/span><span style=\"color:#66d9ef\">function<\/span>(...<span style=\"color:#a6e22e\">selectors<\/span>: <span style=\"color:#66d9ef\">any<\/span>[]) {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#a6e22e\">projector<\/span>.<span style=\"color:#a6e22e\">apply<\/span>(<span style=\"color:#66d9ef\">null<\/span>, <span style=\"color:#a6e22e\">selectors<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>});\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">memoizedState<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">defaultMemoize<\/span>(<span style=\"color:#75715e\">\/* #1 *\/<\/span><span style=\"color:#66d9ef\">function<\/span>(<span style=\"color:#a6e22e\">state<\/span>: <span style=\"color:#66d9ef\">any<\/span>, <span style=\"color:#a6e22e\">props<\/span>: <span style=\"color:#66d9ef\">any<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#a6e22e\">options<\/span>.<span style=\"color:#a6e22e\">stateFn<\/span>.<span style=\"color:#a6e22e\">apply<\/span>(<span style=\"color:#66d9ef\">null<\/span>, [\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">state<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">selectors<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">props<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">memoizedProjector<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  ]);\n<\/span><\/span><span style=\"display:flex;\"><span>});\n<\/span><\/span><\/code><\/pre><\/div><div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-markdown\" data-lang=\"markdown\"><span style=\"display:flex;\"><span>memoizedState.memoized(state) ---compare crtArgs with prevArgs---&gt; #1(state) -&gt; invoke selectors with the given <span style=\"color:#e6db74\">`state`<\/span> ----selectorResults---&gt; memoizedProjector(selectorResults) ---compare crtArgs with prevArgs---&gt; #2(selectorResults)\n<\/span><\/span><\/code><\/pre><\/div><p>After the first call, <code>memoizedState.memoized(state)<\/code> will be the result of <code>#2(selectorResults)<\/code>.<\/p>\n<p>On subsequent calls, <code>memoizedState.memoized(state)<\/code> will not necessarily follow the same path.<br>\nFor example, <code>state<\/code> is the same object, it will stop here, since <code>prevArgs<\/code>(previous state) equals to <code>crtArgs<\/code>(current state):<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-markdown\" data-lang=\"markdown\"><span style=\"display:flex;\"><span>memoizedState.memoized(state) ---compare crtArgs with prevArgs---&gt; prevArgs\n<\/span><\/span><\/code><\/pre><\/div><p>This also justifies why we should always strive for immutability.<br>\nImagine you have a custom selector, which takes a <code>userSelector<\/code> created by <code>createSelector()<\/code> that depends on <code>feat.users<\/code>. When adding a new user to <code>feat.users<\/code>, if you&rsquo;re not creating a new reference of that array, the projection function of <code>userSelector<\/code> will return the memoized value, because the reference would be same.<\/p>\n<h2 id=\"state\">\n  <span>\n  State\n  <\/span>\n  <a href=\"#state\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><p>Among other traits, this is the place where the application\u2019s information is kept.<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">constructor<\/span>(\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">actions$<\/span>: <span style=\"color:#66d9ef\">ActionsSubject<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">reducer$<\/span>: <span style=\"color:#66d9ef\">ReducerObservable<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">scannedActions<\/span>: <span style=\"color:#66d9ef\">ScannedActionsSubject<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">@Inject<\/span>(<span style=\"color:#a6e22e\">INITIAL_STATE<\/span>) <span style=\"color:#a6e22e\">initialState<\/span>: <span style=\"color:#66d9ef\">any<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>) { <span style=\"color:#75715e\">\/* ... *\/<\/span> }\n<\/span><\/span><\/code><\/pre><\/div><ul>\n<li><code>actions$<\/code>: a <code>BehaviorSubject<\/code> that will emit every time an action is dispatched(i.e: <code>store.dispatch(newAction())<\/code>)<\/li>\n<li><code>reducer$<\/code>: a <code>BehaviorSubject<\/code> whose values are functions that, when invoked, will iterate over all the registered reducers and will execute them with the current state and the action that caused the function&rsquo;s invocation<\/li>\n<li><code>scannedActions<\/code>: used to inform other entities(e.g: <code>effects<\/code>) that some action occurred<\/li>\n<\/ul>\n<p>None of the above parameters have access modifiers, which indicates that most of the logic will happen inside the <code>constructor<\/code>:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">constructor<\/span> (<span style=\"color:#75715e\">\/* ... *\/<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">super<\/span>(<span style=\"color:#a6e22e\">initialState<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">actionsOnQueue$<\/span>: <span style=\"color:#66d9ef\">Observable<\/span>&lt;<span style=\"color:#f92672\">Action<\/span>&gt; <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">actions$<\/span>.<span style=\"color:#a6e22e\">pipe<\/span>(\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">observeOn<\/span>(<span style=\"color:#a6e22e\">queueScheduler<\/span>)\n<\/span><\/span><span style=\"display:flex;\"><span>  );\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">withLatestReducer$<\/span>: <span style=\"color:#66d9ef\">Observable<\/span><span style=\"color:#f92672\">&lt;<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>    [<span style=\"color:#a6e22e\">Action<\/span>, <span style=\"color:#a6e22e\">ActionReducer<\/span>&lt;<span style=\"color:#f92672\">any<\/span><span style=\"color:#960050;background-color:#1e0010\">,<\/span> <span style=\"color:#a6e22e\">Action<\/span>&gt;]\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#f92672\">&gt;<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">actionsOnQueue$<\/span>.<span style=\"color:#a6e22e\">pipe<\/span>(<span style=\"color:#a6e22e\">withLatestFrom<\/span>(<span style=\"color:#a6e22e\">reducer$<\/span>));\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">seed<\/span>: <span style=\"color:#66d9ef\">StateActionPair<\/span>&lt;<span style=\"color:#f92672\">T<\/span>&gt; <span style=\"color:#f92672\">=<\/span> { <span style=\"color:#a6e22e\">state<\/span>: <span style=\"color:#66d9ef\">initialState<\/span> };\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">stateAndAction$<\/span>: <span style=\"color:#66d9ef\">Observable<\/span><span style=\"color:#f92672\">&lt;<\/span>{\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">state<\/span>: <span style=\"color:#66d9ef\">any<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">action?<\/span>: <span style=\"color:#66d9ef\">Action<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>  }<span style=\"color:#f92672\">&gt;<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">withLatestReducer$<\/span>.<span style=\"color:#a6e22e\">pipe<\/span>(\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">scan<\/span><span style=\"color:#f92672\">&lt;<\/span>[<span style=\"color:#a6e22e\">Action<\/span>, <span style=\"color:#a6e22e\">ActionReducer<\/span>&lt;<span style=\"color:#f92672\">T<\/span><span style=\"color:#960050;background-color:#1e0010\">,<\/span> <span style=\"color:#a6e22e\">Action<\/span>&gt;], <span style=\"color:#a6e22e\">StateActionPair<\/span>&lt;<span style=\"color:#f92672\">T<\/span>&gt;<span style=\"color:#f92672\">&gt;<\/span>(\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#a6e22e\">reduceState<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#a6e22e\">seed<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>    )\n<\/span><\/span><span style=\"display:flex;\"><span>  );\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">stateSubscription<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">stateAndAction$<\/span>.<span style=\"color:#a6e22e\">subscribe<\/span>(({ <span style=\"color:#a6e22e\">state<\/span>, <span style=\"color:#a6e22e\">action<\/span> }) <span style=\"color:#f92672\">=&gt;<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">next<\/span>(<span style=\"color:#a6e22e\">state<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">scannedActions<\/span>.<span style=\"color:#a6e22e\">next<\/span>(<span style=\"color:#a6e22e\">action<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>  });\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p>This is the place where <code>actions<\/code> are intercepted and applied to the existing reducers. After the reducers are called with the new action, the resulted state will be sent to the consumers. In this case, it is the <code>Store<\/code> entity, because it acts as a middleman between the consumer(e.g: a component, a service) and the <code>State<\/code>(the model, where the information is stored). This can be seen from this line of <code>Store<\/code> class: <code>this.source = state$;<\/code>.<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">withLatestReducer$<\/span>: <span style=\"color:#66d9ef\">Observable<\/span><span style=\"color:#f92672\">&lt;<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>    [<span style=\"color:#a6e22e\">Action<\/span>, <span style=\"color:#a6e22e\">ActionReducer<\/span>&lt;<span style=\"color:#f92672\">any<\/span><span style=\"color:#960050;background-color:#1e0010\">,<\/span> <span style=\"color:#a6e22e\">Action<\/span>&gt;]\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#f92672\">&gt;<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">actionsOnQueue$<\/span>.<span style=\"color:#a6e22e\">pipe<\/span>(<span style=\"color:#a6e22e\">withLatestFrom<\/span>(<span style=\"color:#a6e22e\">reducer$<\/span>));\n<\/span><\/span><\/code><\/pre><\/div><p>Will make sure that although <code>actionsOnQueue$<\/code> emits, if <code>reducer$<\/code> didn&rsquo;t, no values will be pushed forwards into the stream. If both emitted, the values will be emitted only if the observable which emits again is <code>actionsOnQueue$<\/code>. This way, if reducers are added\/removed later, each new action will be applied to the <em>most up to date<\/em> reducers object.<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-markdown\" data-lang=\"markdown\"><span style=\"display:flex;\"><span>-A---A--A--A-----A--&gt; actionsOnQueue$\n<\/span><\/span><span style=\"display:flex;\"><span>       \/  \/    \/\n<\/span><\/span><span style=\"display:flex;\"><span>      |  \/    \/\n<\/span><\/span><span style=\"display:flex;\"><span>------R------R------&gt; reducer$\n<\/span><\/span><\/code><\/pre><\/div><div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">seed<\/span>: <span style=\"color:#66d9ef\">StateActionPair<\/span>&lt;<span style=\"color:#f92672\">T<\/span>&gt; <span style=\"color:#f92672\">=<\/span> { <span style=\"color:#a6e22e\">state<\/span>: <span style=\"color:#66d9ef\">initialState<\/span> };\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">stateAndAction$<\/span>: <span style=\"color:#66d9ef\">Observable<\/span><span style=\"color:#f92672\">&lt;<\/span>{\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">state<\/span>: <span style=\"color:#66d9ef\">any<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">action?<\/span>: <span style=\"color:#66d9ef\">Action<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>}<span style=\"color:#f92672\">&gt;<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">withLatestReducer$<\/span>.<span style=\"color:#a6e22e\">pipe<\/span>(\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">scan<\/span><span style=\"color:#f92672\">&lt;<\/span>[<span style=\"color:#a6e22e\">Action<\/span>, <span style=\"color:#a6e22e\">ActionReducer<\/span>&lt;<span style=\"color:#f92672\">T<\/span><span style=\"color:#960050;background-color:#1e0010\">,<\/span> <span style=\"color:#a6e22e\">Action<\/span>&gt;], <span style=\"color:#a6e22e\">StateActionPair<\/span>&lt;<span style=\"color:#f92672\">T<\/span>&gt;<span style=\"color:#f92672\">&gt;<\/span>(\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">reduceState<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">seed<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>  )\n<\/span><\/span><span style=\"display:flex;\"><span>);\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">export<\/span> <span style=\"color:#66d9ef\">function<\/span> <span style=\"color:#a6e22e\">reduceState<\/span>&lt;<span style=\"color:#f92672\">T<\/span><span style=\"color:#960050;background-color:#1e0010\">,<\/span> <span style=\"color:#a6e22e\">V<\/span> <span style=\"color:#a6e22e\">extends<\/span> <span style=\"color:#a6e22e\">Action <\/span><span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">Action<\/span>&gt;(\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">stateActionPair<\/span>: <span style=\"color:#66d9ef\">StateActionPair<\/span>&lt;<span style=\"color:#f92672\">T<\/span><span style=\"color:#960050;background-color:#1e0010\">,<\/span> <span style=\"color:#a6e22e\">V<\/span>&gt; <span style=\"color:#f92672\">=<\/span> { <span style=\"color:#a6e22e\">state<\/span>: <span style=\"color:#66d9ef\">undefined<\/span> },\n<\/span><\/span><span style=\"display:flex;\"><span>  [<span style=\"color:#a6e22e\">action<\/span>, <span style=\"color:#a6e22e\">reducer<\/span>]<span style=\"color:#f92672\">:<\/span> [<span style=\"color:#a6e22e\">V<\/span>, <span style=\"color:#a6e22e\">ActionReducer<\/span>&lt;<span style=\"color:#f92672\">T<\/span><span style=\"color:#960050;background-color:#1e0010\">,<\/span> <span style=\"color:#a6e22e\">V<\/span>&gt;]\n<\/span><\/span><span style=\"display:flex;\"><span>)<span style=\"color:#f92672\">:<\/span> <span style=\"color:#a6e22e\">StateActionPair<\/span>&lt;<span style=\"color:#f92672\">T<\/span><span style=\"color:#960050;background-color:#1e0010\">,<\/span> <span style=\"color:#a6e22e\">V<\/span>&gt; {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">const<\/span> { <span style=\"color:#a6e22e\">state<\/span> } <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">stateActionPair<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">return<\/span> { <span style=\"color:#a6e22e\">state<\/span>: <span style=\"color:#66d9ef\">reducer<\/span>(<span style=\"color:#a6e22e\">state<\/span>, <span style=\"color:#a6e22e\">action<\/span>), <span style=\"color:#a6e22e\">action<\/span> };\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p><code>reducer<\/code>, when called, will loop through the provided reducers and will call them with the existing state and with the current action. It will eventually return a new state which will be pushed forwards into the stream:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">stateSubscription<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">stateAndAction$<\/span>.<span style=\"color:#a6e22e\">subscribe<\/span>(({ <span style=\"color:#a6e22e\">state<\/span>, <span style=\"color:#a6e22e\">action<\/span> }) <span style=\"color:#f92672\">=&gt;<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">next<\/span>(<span style=\"color:#a6e22e\">state<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">scannedActions<\/span>.<span style=\"color:#a6e22e\">next<\/span>(<span style=\"color:#a6e22e\">action<\/span>); <span style=\"color:#75715e\">\/\/ Send the action to the effects\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>});\n<\/span><\/span><\/code><\/pre><\/div><p>As mentioned before, this stream is the source of the <code>Store<\/code> entity, which is how the data consumers can be notified of new state changes.<\/p>\n<h2 id=\"meta-reducers\">\n  <span>\n  Meta-reducers\n  <\/span>\n  <a href=\"#meta-reducers\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><p>Simply put, meta-reducers are functions that receive a reducer and return a reducer. Additionally, in the same way that interceptors act on an HTTP request, meta-reducers can add behavior before and after a reducer is invoked.<\/p>\n<h3 id=\"setting-up-meta-reducers\">\n  <span>\n  Setting up meta-reducers\n  <\/span>\n  <a href=\"#setting-up-meta-reducers\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h3><div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">export<\/span> <span style=\"color:#66d9ef\">class<\/span> <span style=\"color:#a6e22e\">StoreModule<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">static<\/span> <span style=\"color:#a6e22e\">forRoot<\/span>(\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">reducers<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">config<\/span>: <span style=\"color:#66d9ef\">RootStoreConfig<\/span>&lt;<span style=\"color:#f92672\">any<\/span><span style=\"color:#960050;background-color:#1e0010\">,<\/span> <span style=\"color:#a6e22e\">any<\/span>&gt; <span style=\"color:#f92672\">=<\/span> {}\n<\/span><\/span><span style=\"display:flex;\"><span>  )<span style=\"color:#f92672\">:<\/span> <span style=\"color:#a6e22e\">ModuleWithProviders<\/span>&lt;<span style=\"color:#f92672\">StoreRootModule<\/span>&gt; {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">return<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#a6e22e\">ngModule<\/span>: <span style=\"color:#66d9ef\">StoreRootModule<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#a6e22e\">providers<\/span><span style=\"color:#f92672\">:<\/span> [\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#75715e\">\/* ... *\/<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>        {\n<\/span><\/span><span style=\"display:flex;\"><span>          <span style=\"color:#a6e22e\">provide<\/span>: <span style=\"color:#66d9ef\">USER_PROVIDED_META_REDUCERS<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>          <span style=\"color:#a6e22e\">useValue<\/span>: <span style=\"color:#66d9ef\">config.metaReducers<\/span> <span style=\"color:#f92672\">?<\/span> <span style=\"color:#a6e22e\">config<\/span>.<span style=\"color:#a6e22e\">metaReducers<\/span> <span style=\"color:#f92672\">:<\/span> [],\n<\/span><\/span><span style=\"display:flex;\"><span>        },\n<\/span><\/span><span style=\"display:flex;\"><span>        {\n<\/span><\/span><span style=\"display:flex;\"><span>          <span style=\"color:#a6e22e\">provide<\/span>: <span style=\"color:#66d9ef\">_RESOLVED_META_REDUCERS<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>          <span style=\"color:#a6e22e\">deps<\/span><span style=\"color:#f92672\">:<\/span> [<span style=\"color:#a6e22e\">META_REDUCERS<\/span>, <span style=\"color:#a6e22e\">USER_PROVIDED_META_REDUCERS<\/span>],\n<\/span><\/span><span style=\"display:flex;\"><span>          <span style=\"color:#a6e22e\">useFactory<\/span>: <span style=\"color:#66d9ef\">_concatMetaReducers<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>        },\n<\/span><\/span><span style=\"display:flex;\"><span>        {\n<\/span><\/span><span style=\"display:flex;\"><span>          <span style=\"color:#a6e22e\">provide<\/span>: <span style=\"color:#66d9ef\">REDUCER_FACTORY<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>          <span style=\"color:#a6e22e\">deps<\/span><span style=\"color:#f92672\">:<\/span> [<span style=\"color:#a6e22e\">_REDUCER_FACTORY<\/span>, <span style=\"color:#a6e22e\">_RESOLVED_META_REDUCERS<\/span>],\n<\/span><\/span><span style=\"display:flex;\"><span>          <span style=\"color:#a6e22e\">useFactory<\/span>: <span style=\"color:#66d9ef\">createReducerFactory<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>        },\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#75715e\">\/* ... *\/<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>      ]\n<\/span><\/span><span style=\"display:flex;\"><span>    }\n<\/span><\/span><span style=\"display:flex;\"><span>  }\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p><code>_RESOLVED_META_REDUCERS<\/code> when injected in <code>createReducerFactory<\/code>, it will be an array resulted from merging the built-in meta-reducers with the custom ones.<\/p>\n<p>There are 3 built-in meta-reducers: <code>immutabilityCheckMetaReducer<\/code>, <code>serializationCheckMetaReducer<\/code> and <code>inNgZoneAssertMetaReducer<\/code>.<\/p>\n<p><code>createReducerFactory<\/code> will return a function that will be called with 2 arguments: <code>reducers<\/code> and <code>initialState<\/code>. At the beginning, when the app is barely loaded, the function will be called with the arguments provided in <code>StoreModule.forRoot({ reducers, }, { initialState })<\/code>. When called, it will create a chain(<em>sort of linked list<\/em>) of meta-reducers, whose extremity is going to be the reducer. This way, each meta-reducer can add behavior before and after the reducer&rsquo;s invocation.<br>\nThe reason it returns that function is that <code>createReducerFactory<\/code> will be called when <code>REDUCER_FACTORY<\/code> is injected in <code>ReducerManager<\/code> class. <code>ReducerManager<\/code> will keep reducers up to date when features are added\/removed. So, for instance, when a feature comes with its reducer, <code>ReducerManager<\/code> will combine the existing reducer with the new one.<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">addReducers<\/span>(<span style=\"color:#a6e22e\">reducers<\/span><span style=\"color:#f92672\">:<\/span> { [<span style=\"color:#a6e22e\">key<\/span>: <span style=\"color:#66d9ef\">string<\/span>]<span style=\"color:#f92672\">:<\/span> <span style=\"color:#a6e22e\">ActionReducer<\/span>&lt;<span style=\"color:#f92672\">any<\/span><span style=\"color:#960050;background-color:#1e0010\">,<\/span> <span style=\"color:#a6e22e\">any<\/span>&gt; }) {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">reducers<\/span> <span style=\"color:#f92672\">=<\/span> { ...<span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">reducers<\/span>, ...<span style=\"color:#a6e22e\">reducers<\/span> };\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">updateReducers<\/span>(Object.<span style=\"color:#a6e22e\">keys<\/span>(<span style=\"color:#a6e22e\">reducers<\/span>));\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p>then it will re-create the chain, so that meta-reducers can be applied properly:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">private<\/span> <span style=\"color:#a6e22e\">updateReducers<\/span>(<span style=\"color:#a6e22e\">featureKeys<\/span>: <span style=\"color:#66d9ef\">string<\/span>[]) {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">next<\/span>(<span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">reducerFactory<\/span>(<span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">reducers<\/span>, <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">initialState<\/span>)); <span style=\"color:#75715e\">\/\/ &lt;- re-create the chain\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>  <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">dispatcher<\/span>.<span style=\"color:#a6e22e\">next<\/span>(&lt;<span style=\"color:#f92672\">Action<\/span>&gt;{\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">type<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#a6e22e\">UPDATE<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">features<\/span>: <span style=\"color:#66d9ef\">featureKeys<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  });\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">export<\/span> <span style=\"color:#66d9ef\">function<\/span> <span style=\"color:#a6e22e\">createReducerFactory<\/span>&lt;<span style=\"color:#f92672\">T<\/span><span style=\"color:#960050;background-color:#1e0010\">,<\/span> <span style=\"color:#a6e22e\">V<\/span> <span style=\"color:#a6e22e\">extends<\/span> <span style=\"color:#a6e22e\">Action <\/span><span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">Action<\/span>&gt;(\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">reducerFactory<\/span>: <span style=\"color:#66d9ef\">ActionReducerFactory<\/span>&lt;<span style=\"color:#f92672\">T<\/span><span style=\"color:#960050;background-color:#1e0010\">,<\/span> <span style=\"color:#a6e22e\">V<\/span>&gt;,\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">metaReducers?<\/span>: <span style=\"color:#66d9ef\">MetaReducer<\/span>&lt;<span style=\"color:#f92672\">T<\/span><span style=\"color:#960050;background-color:#1e0010\">,<\/span> <span style=\"color:#a6e22e\">V<\/span>&gt;[]\n<\/span><\/span><span style=\"display:flex;\"><span>)<span style=\"color:#f92672\">:<\/span> <span style=\"color:#a6e22e\">ActionReducerFactory<\/span>&lt;<span style=\"color:#f92672\">T<\/span><span style=\"color:#960050;background-color:#1e0010\">,<\/span> <span style=\"color:#a6e22e\">V<\/span>&gt; {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#75715e\">\/\/ Setting up the `chain` - not created yet!\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>  <span style=\"color:#66d9ef\">if<\/span> (Array.<span style=\"color:#a6e22e\">isArray<\/span>(<span style=\"color:#a6e22e\">metaReducers<\/span>) <span style=\"color:#f92672\">&amp;&amp;<\/span> <span style=\"color:#a6e22e\">metaReducers<\/span>.<span style=\"color:#a6e22e\">length<\/span> <span style=\"color:#f92672\">&gt;<\/span> <span style=\"color:#ae81ff\">0<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>    (<span style=\"color:#a6e22e\">reducerFactory<\/span> <span style=\"color:#66d9ef\">as<\/span> <span style=\"color:#66d9ef\">any<\/span>) <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">compose<\/span>.<span style=\"color:#a6e22e\">apply<\/span>(<span style=\"color:#66d9ef\">null<\/span>, [\n<\/span><\/span><span style=\"display:flex;\"><span>      ...<span style=\"color:#a6e22e\">metaReducers<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#a6e22e\">reducerFactory<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>    ]);\n<\/span><\/span><span style=\"display:flex;\"><span>  }\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">return<\/span> (<span style=\"color:#a6e22e\">reducers<\/span>: <span style=\"color:#66d9ef\">ActionReducerMap<\/span>&lt;<span style=\"color:#f92672\">T<\/span><span style=\"color:#960050;background-color:#1e0010\">,<\/span> <span style=\"color:#a6e22e\">V<\/span>&gt;, <span style=\"color:#a6e22e\">initialState?<\/span>: <span style=\"color:#66d9ef\">InitialState<\/span>&lt;<span style=\"color:#f92672\">T<\/span>&gt;) <span style=\"color:#f92672\">=&gt;<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">reducer<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">reducerFactory<\/span>(<span style=\"color:#a6e22e\">reducers<\/span>); <span style=\"color:#75715e\">\/\/ &lt;- chain created\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>    <span style=\"color:#66d9ef\">return<\/span> (<span style=\"color:#a6e22e\">state<\/span>: <span style=\"color:#66d9ef\">T<\/span> <span style=\"color:#f92672\">|<\/span> <span style=\"color:#66d9ef\">undefined<\/span>, <span style=\"color:#a6e22e\">action<\/span>: <span style=\"color:#66d9ef\">V<\/span>) <span style=\"color:#f92672\">=&gt;<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#a6e22e\">state<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">state<\/span> <span style=\"color:#f92672\">===<\/span> <span style=\"color:#66d9ef\">undefined<\/span> <span style=\"color:#f92672\">?<\/span> (<span style=\"color:#a6e22e\">initialState<\/span> <span style=\"color:#66d9ef\">as<\/span> <span style=\"color:#a6e22e\">T<\/span>) <span style=\"color:#f92672\">:<\/span> <span style=\"color:#a6e22e\">state<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#a6e22e\">reducer<\/span>(<span style=\"color:#a6e22e\">state<\/span>, <span style=\"color:#a6e22e\">action<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>    };\n<\/span><\/span><span style=\"display:flex;\"><span>  };\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p>The gist resides in <code>compose<\/code>:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">export<\/span> <span style=\"color:#66d9ef\">function<\/span> <span style=\"color:#a6e22e\">compose<\/span>(...<span style=\"color:#a6e22e\">functions<\/span>: <span style=\"color:#66d9ef\">any<\/span>[]) {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#66d9ef\">function<\/span>(<span style=\"color:#a6e22e\">arg<\/span>: <span style=\"color:#66d9ef\">any<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#a6e22e\">functions<\/span>.<span style=\"color:#a6e22e\">length<\/span> <span style=\"color:#f92672\">===<\/span> <span style=\"color:#ae81ff\">0<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#a6e22e\">arg<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>    }\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">last<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">functions<\/span>[<span style=\"color:#a6e22e\">functions<\/span>.<span style=\"color:#a6e22e\">length<\/span> <span style=\"color:#f92672\">-<\/span> <span style=\"color:#ae81ff\">1<\/span>];\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">rest<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">functions<\/span>.<span style=\"color:#a6e22e\">slice<\/span>(<span style=\"color:#ae81ff\">0<\/span>, <span style=\"color:#f92672\">-<\/span><span style=\"color:#ae81ff\">1<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#a6e22e\">rest<\/span>.<span style=\"color:#a6e22e\">reduceRight<\/span>((<span style=\"color:#a6e22e\">composed<\/span>, <span style=\"color:#a6e22e\">fn<\/span>) <span style=\"color:#f92672\">=&gt;<\/span> <span style=\"color:#a6e22e\">fn<\/span>(<span style=\"color:#a6e22e\">composed<\/span>), <span style=\"color:#a6e22e\">last<\/span>(<span style=\"color:#a6e22e\">arg<\/span>));\n<\/span><\/span><span style=\"display:flex;\"><span>  };\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p>where <code>functions<\/code> is an array of meta-reducers followed by the function that will combine the reducers in a single reducer object and <code>arg<\/code> will be reducers that will have to be combined.<\/p>\n<p>This could be visualized as follows:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-markdown\" data-lang=\"markdown\"><span style=\"display:flex;\"><span>\/\/ m-r -&gt; meta-reducer\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>const myMetaReducer = (reducer) =&gt; (state, action) =&gt; {\n<\/span><\/span><span style=\"display:flex;\"><span>  \/* Logic before reducer&#39;s invocation *\/\n<\/span><\/span><span style=\"display:flex;\"><span>  \n<\/span><\/span><span style=\"display:flex;\"><span>  const result = reducer(state, action); \/\/ Invoke the reducer -&gt; will return the new state\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>  \/* Logic after reducer&#39;s invocation *\/\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>  return result; \/\/ Return it so other meta-reducers can access the new produced state\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>rest.reduceRight((composed, fn) =&gt; fn(composed), last(arg)); \/\/ &lt;<span style=\"color:#f92672\">-<\/span> <span style=\"color:#e6db74\">`last(args)`<\/span> <span style=\"color:#a6e22e\">will<\/span> <span style=\"color:#a6e22e\">create<\/span> <span style=\"color:#a6e22e\">the<\/span> <span style=\"color:#a6e22e\">reducers<\/span> <span style=\"color:#a6e22e\">object<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>                       <span style=\"color:#960050;background-color:#1e0010\">|<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>                       <span style=\"color:#960050;background-color:#1e0010\">|<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>                       <span style=\"color:#960050;background-color:#1e0010\">\u2b07<\/span><span style=\"color:#a6e22e\">\ufe0f<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">----------<\/span>\u2008  <span style=\"color:#a6e22e\">reducer<\/span><span style=\"color:#960050;background-color:#1e0010\">()<\/span>    <span style=\"color:#a6e22e\">----------<\/span>\u2008  <span style=\"color:#a6e22e\">reducer<\/span><span style=\"color:#960050;background-color:#1e0010\">()<\/span>    <span style=\"color:#a6e22e\">-------------<\/span>\u2008 \n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#960050;background-color:#1e0010\">|<\/span>        <span style=\"color:#960050;background-color:#1e0010\">|<\/span><span style=\"color:#a6e22e\">---------------<\/span>&gt;|        |---------------&gt;|           |\u2008\n<\/span><\/span><span style=\"display:flex;\"><span>|  m-r1  |\u2008               |  m-r2  |\u2008               |  reducer  |\u2008  &lt;<span style=\"color:#f92672\">-<\/span> <span style=\"color:#960050;background-color:#1e0010\">\/\/<\/span> <span style=\"color:#a6e22e\">new<\/span> <span style=\"color:#a6e22e\">state<\/span> <span style=\"color:#a6e22e\">is<\/span> <span style=\"color:#a6e22e\">produced<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#960050;background-color:#1e0010\">|<\/span>        <span style=\"color:#960050;background-color:#1e0010\">|&lt;<\/span><span style=\"color:#a6e22e\">---------------<\/span><span style=\"color:#960050;background-color:#1e0010\">|<\/span>        <span style=\"color:#960050;background-color:#1e0010\">|&lt;<\/span><span style=\"color:#a6e22e\">---------------<\/span><span style=\"color:#960050;background-color:#1e0010\">|<\/span>           <span style=\"color:#960050;background-color:#1e0010\">|<\/span>\u2008  \n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">----------<\/span>\u2008   <span style=\"color:#a6e22e\">newState<\/span>    <span style=\"color:#a6e22e\">----------<\/span>\u2008   <span style=\"color:#a6e22e\">newState<\/span>    <span style=\"color:#a6e22e\">-------------<\/span>\u2008    \n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#960050;background-color:#1e0010\">|<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#960050;background-color:#1e0010\">|<\/span>  <span style=\"color:#960050;background-color:#1e0010\">\/\/<\/span> <span style=\"color:#a6e22e\">returned<\/span> <span style=\"color:#a6e22e\">reducer<\/span><span style=\"color:#960050;background-color:#1e0010\">;<\/span> <span style=\"color:#a6e22e\">when<\/span> <span style=\"color:#a6e22e\">called<\/span><span style=\"color:#960050;background-color:#1e0010\">,<\/span> <span style=\"color:#a6e22e\">it<\/span> <span style=\"color:#a6e22e\">will<\/span> <span style=\"color:#a6e22e\">in<\/span> <span style=\"color:#a6e22e\">turn<\/span> <span style=\"color:#a6e22e\">call<\/span> <span style=\"color:#a6e22e\">the<\/span> <span style=\"color:#a6e22e\">reducer<\/span> <span style=\"color:#a6e22e\">received<\/span> <span style=\"color:#a6e22e\">as<\/span> <span style=\"color:#a6e22e\">an<\/span> <span style=\"color:#a6e22e\">argument<\/span><span style=\"color:#960050;background-color:#1e0010\">;<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#960050;background-color:#1e0010\">|<\/span>  <span style=\"color:#960050;background-color:#1e0010\">\/\/<\/span> <span style=\"color:#a6e22e\">that<\/span> <span style=\"color:#a6e22e\">argument<\/span> <span style=\"color:#960050;background-color:#1e0010\">&#39;<\/span><span style=\"color:#a6e22e\">points<\/span><span style=\"color:#960050;background-color:#1e0010\">&#39;<\/span> <span style=\"color:#a6e22e\">to<\/span> <span style=\"color:#a6e22e\">the<\/span> <span style=\"color:#a6e22e\">previous<\/span> <span style=\"color:#a6e22e\">reducer<\/span> <span style=\"color:#a6e22e\">in<\/span> <span style=\"color:#a6e22e\">the<\/span> <span style=\"color:#a6e22e\">chain<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#960050;background-color:#1e0010\">\u2b07<\/span><span style=\"color:#a6e22e\">\ufe0f<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">reducer<\/span><span style=\"color:#960050;background-color:#1e0010\">(<\/span><span style=\"color:#a6e22e\">state<\/span><span style=\"color:#960050;background-color:#1e0010\">,<\/span> <span style=\"color:#a6e22e\">action<\/span><span style=\"color:#960050;background-color:#1e0010\">)<\/span>\n<\/span><\/span><\/code><\/pre><\/div><h3 id=\"providing-custom-meta-reducers\">\n  <span>\n  Providing custom meta-reducers\n  <\/span>\n  <a href=\"#providing-custom-meta-reducers\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h3><p>Armed with the knowledge from the previous section, we can now explore how to use custom meta-reducers.<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">export<\/span> <span style=\"color:#66d9ef\">class<\/span> <span style=\"color:#a6e22e\">StoreModule<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">static<\/span> <span style=\"color:#a6e22e\">forRoot<\/span>(\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">reducers<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">config<\/span>: <span style=\"color:#66d9ef\">RootStoreConfig<\/span>&lt;<span style=\"color:#f92672\">any<\/span><span style=\"color:#960050;background-color:#1e0010\">,<\/span> <span style=\"color:#a6e22e\">any<\/span>&gt; <span style=\"color:#f92672\">=<\/span> {}\n<\/span><\/span><span style=\"display:flex;\"><span>  )<span style=\"color:#f92672\">:<\/span> <span style=\"color:#a6e22e\">ModuleWithProviders<\/span>&lt;<span style=\"color:#f92672\">StoreRootModule<\/span>&gt; {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">return<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#a6e22e\">ngModule<\/span>: <span style=\"color:#66d9ef\">StoreRootModule<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#a6e22e\">providers<\/span><span style=\"color:#f92672\">:<\/span> [\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#75715e\">\/* ... *\/<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>        {\n<\/span><\/span><span style=\"display:flex;\"><span>          <span style=\"color:#a6e22e\">provide<\/span>: <span style=\"color:#66d9ef\">USER_PROVIDED_META_REDUCERS<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>          <span style=\"color:#a6e22e\">useValue<\/span>: <span style=\"color:#66d9ef\">config.metaReducers<\/span> <span style=\"color:#f92672\">?<\/span> <span style=\"color:#a6e22e\">config<\/span>.<span style=\"color:#a6e22e\">metaReducers<\/span> <span style=\"color:#f92672\">:<\/span> [],\n<\/span><\/span><span style=\"display:flex;\"><span>        },\n<\/span><\/span><span style=\"display:flex;\"><span>        {\n<\/span><\/span><span style=\"display:flex;\"><span>          <span style=\"color:#a6e22e\">provide<\/span>: <span style=\"color:#66d9ef\">_RESOLVED_META_REDUCERS<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>          <span style=\"color:#a6e22e\">deps<\/span><span style=\"color:#f92672\">:<\/span> [<span style=\"color:#a6e22e\">META_REDUCERS<\/span>, <span style=\"color:#a6e22e\">USER_PROVIDED_META_REDUCERS<\/span>],\n<\/span><\/span><span style=\"display:flex;\"><span>          <span style=\"color:#a6e22e\">useFactory<\/span>: <span style=\"color:#66d9ef\">_concatMetaReducers<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>        },\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#75715e\">\/* ... *\/<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>      ]\n<\/span><\/span><span style=\"display:flex;\"><span>    }\n<\/span><\/span><span style=\"display:flex;\"><span>  }\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/* ... *\/<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">export<\/span> <span style=\"color:#66d9ef\">function<\/span> <span style=\"color:#a6e22e\">_concatMetaReducers<\/span>(\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">metaReducers<\/span>: <span style=\"color:#66d9ef\">MetaReducer<\/span>[],\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">userProvidedMetaReducers<\/span>: <span style=\"color:#66d9ef\">MetaReducer<\/span>[]\n<\/span><\/span><span style=\"display:flex;\"><span>)<span style=\"color:#f92672\">:<\/span> <span style=\"color:#a6e22e\">MetaReducer<\/span>[] {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#a6e22e\">metaReducers<\/span>.<span style=\"color:#a6e22e\">concat<\/span>(<span style=\"color:#a6e22e\">userProvidedMetaReducers<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><h3 id=\"configmetareducers\">\n  <span>\n  <code>config.metaReducers<\/code>\n  <\/span>\n  <a href=\"#configmetareducers\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h3><p><code>RootStoreConfig<\/code>(from above) extends <code>StoreConfig<\/code>:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">export<\/span> <span style=\"color:#66d9ef\">interface<\/span> <span style=\"color:#a6e22e\">StoreConfig<\/span>&lt;<span style=\"color:#f92672\">T<\/span><span style=\"color:#960050;background-color:#1e0010\">,<\/span> <span style=\"color:#a6e22e\">V<\/span> <span style=\"color:#a6e22e\">extends<\/span> <span style=\"color:#a6e22e\">Action <\/span><span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">Action<\/span>&gt; {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">initialState?<\/span>: <span style=\"color:#66d9ef\">InitialState<\/span>&lt;<span style=\"color:#f92672\">T<\/span>&gt;;\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">reducerFactory?<\/span>: <span style=\"color:#66d9ef\">ActionReducerFactory<\/span>&lt;<span style=\"color:#f92672\">T<\/span><span style=\"color:#960050;background-color:#1e0010\">,<\/span> <span style=\"color:#a6e22e\">V<\/span>&gt;;\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">metaReducers?<\/span>: <span style=\"color:#66d9ef\">MetaReducer<\/span>&lt;<span style=\"color:#f92672\">T<\/span><span style=\"color:#960050;background-color:#1e0010\">,<\/span> <span style=\"color:#a6e22e\">V<\/span>&gt;[];\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p>Which means we can provide a custom meta-reducer like this:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">StoreModule<\/span>.<span style=\"color:#a6e22e\">forRoot<\/span>(\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">reducersMap<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  { <span style=\"color:#a6e22e\">metaReducers<\/span>, }\n<\/span><\/span><span style=\"display:flex;\"><span>)\n<\/span><\/span><\/code><\/pre><\/div><p>where <code>metaReducers<\/code> is an array of <code>MetaReducer<\/code>:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">myMetaReducer<\/span>: <span style=\"color:#66d9ef\">MetaReducer<\/span> <span style=\"color:#f92672\">=<\/span> (<span style=\"color:#a6e22e\">reducer<\/span>: <span style=\"color:#66d9ef\">ActionReducer<\/span>&lt;<span style=\"color:#f92672\">any<\/span><span style=\"color:#960050;background-color:#1e0010\">,<\/span> <span style=\"color:#a6e22e\">any<\/span>&gt;) <span style=\"color:#f92672\">=&gt;<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">return<\/span> (<span style=\"color:#a6e22e\">state<\/span>, <span style=\"color:#a6e22e\">action<\/span>) <span style=\"color:#f92672\">=&gt;<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">console<\/span>.<span style=\"color:#a6e22e\">log<\/span>(<span style=\"color:#e6db74\">&#39;before&#39;<\/span>, <span style=\"color:#a6e22e\">action<\/span>, <span style=\"color:#a6e22e\">state<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">result<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">reducer<\/span>(<span style=\"color:#a6e22e\">state<\/span>, <span style=\"color:#a6e22e\">action<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">console<\/span>.<span style=\"color:#a6e22e\">log<\/span>(<span style=\"color:#e6db74\">&#39;after&#39;<\/span>, <span style=\"color:#a6e22e\">result<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#a6e22e\">result<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>  }\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">export<\/span> <span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">metaReducers<\/span>: <span style=\"color:#66d9ef\">MetaReducer<\/span>[] <span style=\"color:#f92672\">=<\/span> [<span style=\"color:#a6e22e\">myMetaReducer<\/span>];\n<\/span><\/span><\/code><\/pre><\/div><h3 id=\"injecting-dependencies-into-a-meta-reducer\">\n  <span>\n  Injecting dependencies into a meta-reducer\n  <\/span>\n  <a href=\"#injecting-dependencies-into-a-meta-reducer\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h3><p>Sometimes we might want to inject dependencies in our meta-reducers. We can take advantage of the <code>META_REDUCER<\/code> multi provider token.<\/p>\n<p>We can inject dependencies by registering the meta-reducer as factory provider with the help of <code>META_REDUCER<\/code>.<\/p>\n<p>For example, we can have something like this:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">export<\/span> <span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">metaReducerWithDepFactory<\/span><span style=\"color:#f92672\">:<\/span> (<span style=\"color:#a6e22e\">d<\/span>: <span style=\"color:#66d9ef\">any<\/span>) <span style=\"color:#f92672\">=&gt;<\/span> <span style=\"color:#a6e22e\">MetaReducer<\/span> <span style=\"color:#f92672\">=<\/span> \n<\/span><\/span><span style=\"display:flex;\"><span>  (<span style=\"color:#a6e22e\">logger<\/span>: <span style=\"color:#66d9ef\">LogService<\/span>) <span style=\"color:#f92672\">=&gt;<\/span> <span style=\"color:#a6e22e\">reducer<\/span> <span style=\"color:#f92672\">=&gt;<\/span> (<span style=\"color:#a6e22e\">state<\/span>, <span style=\"color:#a6e22e\">action<\/span>) <span style=\"color:#f92672\">=&gt;<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">console<\/span>.<span style=\"color:#a6e22e\">log<\/span>(<span style=\"color:#e6db74\">&#39;meta reducer with dep!&#39;<\/span>, <span style=\"color:#a6e22e\">logger<\/span>, <span style=\"color:#a6e22e\">action<\/span>)\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#a6e22e\">reducer<\/span>(<span style=\"color:#a6e22e\">state<\/span>, <span style=\"color:#a6e22e\">action<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p>and we can register it this way:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span>{\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">provide<\/span>: <span style=\"color:#66d9ef\">META_REDUCERS<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">multi<\/span>: <span style=\"color:#66d9ef\">true<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">useFactory<\/span>: <span style=\"color:#66d9ef\">metaReducerWithDepFactory<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">deps<\/span><span style=\"color:#f92672\">:<\/span> [<span style=\"color:#a6e22e\">LogService<\/span>]\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p>You can play around with this example <a href=\"https:\/\/ng-run.com\/edit\/ufX1KYcBMOmV0sp78k7A?open=app%2Ffoo.meta-reducer.ts\" target=\"_blank\" rel=\"noopener\">here<\/a>.<\/p>\n<p>Furthermore, for a better visualization of how things are organized, you can put some breakpoints in your <strong>ng-run<\/strong> tab:<\/p>\n<ul>\n<li><code>foo.meta-reducer.ts<\/code>: line 5<\/li>\n<li><code>utils.ts<\/code>: line 32 -&gt; the <code>combination(state, action)<\/code> function is where the combined reducers are iterated over and invoked<\/li>\n<li><code>foo.meta-reducer.ts<\/code>: line 7<\/li>\n<\/ul>\n<h2 id=\"using-features\">\n  <span>\n  Using Features\n  <\/span>\n  <a href=\"#using-features\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><p>Adding a feature module to a root module (where all the reducers reside) can be seen as adding a decoupled slice of cake back to its initial plate. The initial plate can be thought of as the root module and the slice of cake as the feature module. What this means is that there will still be a single source of truth(<em>the plate<\/em>) but each slice(feature module) can have its own <em>decorations<\/em>(meta-reducers, reducers).<\/p>\n<h3 id=\"registering-feature-modules\">\n  <span>\n  Registering feature modules\n  <\/span>\n  <a href=\"#registering-feature-modules\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h3><p>Registering a feature can be achieved with:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">Store<\/span>.<span style=\"color:#a6e22e\">forFeature<\/span>(<span style=\"color:#a6e22e\">featureName<\/span>, <span style=\"color:#a6e22e\">reducer<\/span>: <span style=\"color:#66d9ef\">ActionReducerMap<\/span> <span style=\"color:#f92672\">|<\/span> <span style=\"color:#a6e22e\">ActionReducer<\/span>, <span style=\"color:#a6e22e\">config<\/span>)\n<\/span><\/span><\/code><\/pre><\/div><p>where <code>reducer<\/code> is either an object of reducers(<code>ActionReducerMap<\/code>) or a function <code>ActionReducer<\/code>.You can register multiple feature modules at once.<\/p>\n<p>Suppose you have something like this:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">StoreModule<\/span>.<span style=\"color:#a6e22e\">forRoot<\/span>({ <span style=\"color:#a6e22e\">foo<\/span>: <span style=\"color:#66d9ef\">fooReducer<\/span> }),\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">StoreModule<\/span>.<span style=\"color:#a6e22e\">forFeature<\/span>(<span style=\"color:#e6db74\">&#39;awesome-feat&#39;<\/span>, { <span style=\"color:#a6e22e\">feat<\/span>: <span style=\"color:#66d9ef\">featReducer<\/span> }), <span style=\"color:#75715e\">\/\/ `reducer` - ActionReducerMap\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span><span style=\"color:#a6e22e\">StoreModule<\/span>.<span style=\"color:#a6e22e\">forFeature<\/span>(<span style=\"color:#e6db74\">&#39;counter&#39;<\/span>, <span style=\"color:#a6e22e\">counterReducer<\/span>), <span style=\"color:#75715e\">\/\/ `reducer` - function\n<\/span><\/span><\/span><\/code><\/pre><\/div><p>After the initialization, our store should look like this:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span>{\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#e6db74\">&#39;foo&#39;<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#75715e\">\/* ... *\/<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#e6db74\">&#39;awesome-feat&#39;<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#75715e\">\/* ... *\/<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#e6db74\">&#39;counter&#39;<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#75715e\">\/* ... *\/<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p>Let\u2019s find out how that happens. It all starts in <code>StoreFeatureModule<\/code>, where all the provided configurations are collected:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">export<\/span> <span style=\"color:#66d9ef\">class<\/span> <span style=\"color:#a6e22e\">StoreFeatureModule<\/span> <span style=\"color:#75715e\">\/* ... *\/<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">constructor<\/span>(\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">@Inject<\/span>(<span style=\"color:#a6e22e\">_STORE_FEATURES<\/span>) <span style=\"color:#66d9ef\">private<\/span> <span style=\"color:#a6e22e\">features<\/span>: <span style=\"color:#66d9ef\">StoreFeature<\/span>&lt;<span style=\"color:#f92672\">any<\/span><span style=\"color:#960050;background-color:#1e0010\">,<\/span> <span style=\"color:#a6e22e\">any<\/span>&gt;[],\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">@Inject<\/span>(<span style=\"color:#a6e22e\">FEATURE_REDUCERS<\/span>) <span style=\"color:#66d9ef\">private<\/span> <span style=\"color:#a6e22e\">featureReducers<\/span>: <span style=\"color:#66d9ef\">ActionReducerMap<\/span>&lt;<span style=\"color:#f92672\">any<\/span>&gt;[],\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">private<\/span> <span style=\"color:#a6e22e\">reducerManager<\/span>: <span style=\"color:#66d9ef\">ReducerManager<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">root<\/span>: <span style=\"color:#66d9ef\">StoreRootModule<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>  ) {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">feats<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">features<\/span>.<span style=\"color:#a6e22e\">map<\/span>((<span style=\"color:#a6e22e\">feature<\/span>, <span style=\"color:#a6e22e\">index<\/span>) <span style=\"color:#f92672\">=&gt;<\/span> { <span style=\"color:#75715e\">\/* ... *\/<\/span> });\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">reducerManager<\/span>.<span style=\"color:#a6e22e\">addFeatures<\/span>(<span style=\"color:#a6e22e\">feats<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>  }\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p>Once everything(initialState, reducers, meta-reducers) is gathered in once place(<code>feats<\/code> array), <code>ReducerManager<\/code> comes in to play. <code>ReducerManager.addFeatures<\/code> will sort out the features&rsquo; reducers. Remember that a feature module&rsquo;s reducer can be either a function or an object of reducers(<em>functions<\/em>).<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">addFeatures<\/span>(<span style=\"color:#a6e22e\">features<\/span>: <span style=\"color:#66d9ef\">StoreFeature<\/span>&lt;<span style=\"color:#f92672\">any<\/span><span style=\"color:#960050;background-color:#1e0010\">,<\/span> <span style=\"color:#a6e22e\">any<\/span>&gt;[]) {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">reducers<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">features<\/span>.<span style=\"color:#a6e22e\">reduce<\/span>(\n<\/span><\/span><span style=\"display:flex;\"><span>    (\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#a6e22e\">reducerDict<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>      { <span style=\"color:#a6e22e\">reducers<\/span>, <span style=\"color:#a6e22e\">reducerFactory<\/span>, <span style=\"color:#a6e22e\">metaReducers<\/span>, <span style=\"color:#a6e22e\">initialState<\/span>, <span style=\"color:#a6e22e\">key<\/span> }\n<\/span><\/span><span style=\"display:flex;\"><span>    ) <span style=\"color:#f92672\">=&gt;<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">reducer<\/span> <span style=\"color:#f92672\">=<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#66d9ef\">typeof<\/span> <span style=\"color:#a6e22e\">reducers<\/span> <span style=\"color:#f92672\">===<\/span> <span style=\"color:#e6db74\">&#39;function&#39;<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>          <span style=\"color:#f92672\">?<\/span> <span style=\"color:#a6e22e\">createFeatureReducerFactory<\/span>(<span style=\"color:#a6e22e\">metaReducers<\/span>)(<span style=\"color:#a6e22e\">reducers<\/span>, <span style=\"color:#a6e22e\">initialState<\/span>)\n<\/span><\/span><span style=\"display:flex;\"><span>          <span style=\"color:#f92672\">:<\/span> <span style=\"color:#a6e22e\">createReducerFactory<\/span>(<span style=\"color:#a6e22e\">reducerFactory<\/span>, <span style=\"color:#a6e22e\">metaReducers<\/span>)(\n<\/span><\/span><span style=\"display:flex;\"><span>              <span style=\"color:#a6e22e\">reducers<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>              <span style=\"color:#a6e22e\">initialState<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>            );\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#a6e22e\">reducerDict<\/span>[<span style=\"color:#a6e22e\">key<\/span>] <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">reducer<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#a6e22e\">reducerDict<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>    },\n<\/span><\/span><span style=\"display:flex;\"><span>    {} <span style=\"color:#66d9ef\">as<\/span> { [<span style=\"color:#a6e22e\">key<\/span>: <span style=\"color:#66d9ef\">string<\/span>]<span style=\"color:#f92672\">:<\/span> <span style=\"color:#a6e22e\">ActionReducer<\/span>&lt;<span style=\"color:#f92672\">any<\/span><span style=\"color:#960050;background-color:#1e0010\">,<\/span> <span style=\"color:#a6e22e\">any<\/span>&gt; }\n<\/span><\/span><span style=\"display:flex;\"><span>  );\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">addReducers<\/span>(<span style=\"color:#a6e22e\">reducers<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p>If it is an object of reducers (<code>{ feat: featReducer }<\/code>), it will follow the same steps as the ones described in &ldquo;How are reducers set up?&rdquo; section above. More concisely, the <code>awesome-feat<\/code>&rsquo;s reducer will be a function that accepts <code>state<\/code> and <code>action<\/code> as arguments and, when invoked, will iterate over the feature&rsquo;s registered reducers(in this case <code>feat<\/code>, which was created by <code>createReducer<\/code>) and will call them with the given arguments. This is actually the <code>combination<\/code> function:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/* ... *\/<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#66d9ef\">function<\/span> <span style=\"color:#a6e22e\">combination<\/span>(<span style=\"color:#a6e22e\">state<\/span>, <span style=\"color:#a6e22e\">action<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">state<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">state<\/span> <span style=\"color:#f92672\">===<\/span> <span style=\"color:#66d9ef\">undefined<\/span> <span style=\"color:#f92672\">?<\/span> <span style=\"color:#a6e22e\">initialState<\/span> : <span style=\"color:#66d9ef\">state<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">let<\/span> <span style=\"color:#a6e22e\">hasChanged<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">false<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">nextState<\/span>: <span style=\"color:#66d9ef\">any<\/span> <span style=\"color:#f92672\">=<\/span> {};\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">for<\/span> (<span style=\"color:#66d9ef\">let<\/span> <span style=\"color:#a6e22e\">i<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#ae81ff\">0<\/span>; <span style=\"color:#a6e22e\">i<\/span> <span style=\"color:#f92672\">&lt;<\/span> <span style=\"color:#a6e22e\">finalReducerKeys<\/span>.<span style=\"color:#a6e22e\">length<\/span>; <span style=\"color:#a6e22e\">i<\/span><span style=\"color:#f92672\">++<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">key<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">finalReducerKeys<\/span>[<span style=\"color:#a6e22e\">i<\/span>];\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">reducer<\/span>: <span style=\"color:#66d9ef\">any<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">finalReducers<\/span>[<span style=\"color:#a6e22e\">key<\/span>];\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">previousStateForKey<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">state<\/span>[<span style=\"color:#a6e22e\">key<\/span>];\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">nextStateForKey<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">reducer<\/span>(<span style=\"color:#a6e22e\">previousStateForKey<\/span>, <span style=\"color:#a6e22e\">action<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">nextState<\/span>[<span style=\"color:#a6e22e\">key<\/span>] <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">nextStateForKey<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">hasChanged<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">hasChanged<\/span> <span style=\"color:#f92672\">||<\/span> <span style=\"color:#a6e22e\">nextStateForKey<\/span> <span style=\"color:#f92672\">!==<\/span> <span style=\"color:#a6e22e\">previousStateForKey<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>  }\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#a6e22e\">hasChanged<\/span> <span style=\"color:#f92672\">?<\/span> <span style=\"color:#a6e22e\">nextState<\/span> : <span style=\"color:#66d9ef\">state<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>};\n<\/span><\/span><\/code><\/pre><\/div><p>If instead the provided feature reducer is function(created by <code>createReducer<\/code>), it will simply invoke it with the <code>state<\/code> and <code>action<\/code> arguments. As with the other approach, the meta-reducer chain will still be created, but the way it is created it slightly different.<\/p>\n<p>That&rsquo;s because when a single function is provided, it means it can&rsquo;t be something more than that, it can&rsquo;t be an object of reducers, so there is no need to create another function that, when called, will iterate over the object of reducers and invoke them(which is what happens when an object of reducers is provided).<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">export<\/span> <span style=\"color:#66d9ef\">function<\/span> <span style=\"color:#a6e22e\">createFeatureReducerFactory<\/span>&lt;<span style=\"color:#f92672\">T<\/span><span style=\"color:#960050;background-color:#1e0010\">,<\/span> <span style=\"color:#a6e22e\">V<\/span> <span style=\"color:#a6e22e\">extends<\/span> <span style=\"color:#a6e22e\">Action <\/span><span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">Action<\/span>&gt;(\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">metaReducers?<\/span>: <span style=\"color:#66d9ef\">MetaReducer<\/span>&lt;<span style=\"color:#f92672\">T<\/span><span style=\"color:#960050;background-color:#1e0010\">,<\/span> <span style=\"color:#a6e22e\">V<\/span>&gt;[]\n<\/span><\/span><span style=\"display:flex;\"><span>)<span style=\"color:#f92672\">:<\/span> (<span style=\"color:#a6e22e\">reducer<\/span>: <span style=\"color:#66d9ef\">ActionReducer<\/span>&lt;<span style=\"color:#f92672\">T<\/span><span style=\"color:#960050;background-color:#1e0010\">,<\/span> <span style=\"color:#a6e22e\">V<\/span>&gt;, <span style=\"color:#a6e22e\">initialState?<\/span>: <span style=\"color:#66d9ef\">T<\/span>) <span style=\"color:#f92672\">=&gt;<\/span> <span style=\"color:#a6e22e\">ActionReducer<\/span>&lt;<span style=\"color:#f92672\">T<\/span><span style=\"color:#960050;background-color:#1e0010\">,<\/span> <span style=\"color:#a6e22e\">V<\/span>&gt; {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#75715e\">\/\/ Pretty similar to the other approach, except that here there is no `combineReducers` function\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>  <span style=\"color:#75715e\">\/\/ because the reducer is one single function\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>  <span style=\"color:#75715e\">\/\/ as opposed to an object of reducers\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>  <span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">reducerFactory<\/span> <span style=\"color:#f92672\">=<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>    Array.<span style=\"color:#a6e22e\">isArray<\/span>(<span style=\"color:#a6e22e\">metaReducers<\/span>) <span style=\"color:#f92672\">&amp;&amp;<\/span> <span style=\"color:#a6e22e\">metaReducers<\/span>.<span style=\"color:#a6e22e\">length<\/span> <span style=\"color:#f92672\">&gt;<\/span> <span style=\"color:#ae81ff\">0<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#f92672\">?<\/span> <span style=\"color:#a6e22e\">compose<\/span>&lt;<span style=\"color:#f92672\">ActionReducer<\/span><span style=\"color:#960050;background-color:#1e0010\">&lt;<\/span><span style=\"color:#a6e22e\">T<\/span><span style=\"color:#960050;background-color:#1e0010\">,<\/span> <span style=\"color:#a6e22e\">V<\/span>&gt;<span style=\"color:#f92672\">&gt;<\/span>(...<span style=\"color:#a6e22e\">metaReducers<\/span>)\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#f92672\">:<\/span> (<span style=\"color:#a6e22e\">r<\/span>: <span style=\"color:#66d9ef\">ActionReducer<\/span>&lt;<span style=\"color:#f92672\">T<\/span><span style=\"color:#960050;background-color:#1e0010\">,<\/span> <span style=\"color:#a6e22e\">V<\/span>&gt;) <span style=\"color:#f92672\">=&gt;<\/span> <span style=\"color:#a6e22e\">r<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">return<\/span> (<span style=\"color:#a6e22e\">reducer<\/span>: <span style=\"color:#66d9ef\">ActionReducer<\/span>&lt;<span style=\"color:#f92672\">T<\/span><span style=\"color:#960050;background-color:#1e0010\">,<\/span> <span style=\"color:#a6e22e\">V<\/span>&gt;, <span style=\"color:#a6e22e\">initialState?<\/span>: <span style=\"color:#66d9ef\">T<\/span>) <span style=\"color:#f92672\">=&gt;<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">reducer<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">reducerFactory<\/span>(<span style=\"color:#a6e22e\">reducer<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">return<\/span> (<span style=\"color:#a6e22e\">state<\/span>: <span style=\"color:#66d9ef\">T<\/span> <span style=\"color:#f92672\">|<\/span> <span style=\"color:#66d9ef\">undefined<\/span>, <span style=\"color:#a6e22e\">action<\/span>: <span style=\"color:#66d9ef\">V<\/span>) <span style=\"color:#f92672\">=&gt;<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#a6e22e\">state<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">state<\/span> <span style=\"color:#f92672\">===<\/span> <span style=\"color:#66d9ef\">undefined<\/span> <span style=\"color:#f92672\">?<\/span> <span style=\"color:#a6e22e\">initialState<\/span> : <span style=\"color:#66d9ef\">state<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#a6e22e\">reducer<\/span>(<span style=\"color:#a6e22e\">state<\/span>, <span style=\"color:#a6e22e\">action<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>    };\n<\/span><\/span><span style=\"display:flex;\"><span>  };\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p>After the reducers have been created accordingly, the single source of truth(the object) will have to be updated:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">addReducers<\/span>(<span style=\"color:#a6e22e\">reducers<\/span><span style=\"color:#f92672\">:<\/span> { [<span style=\"color:#a6e22e\">key<\/span>: <span style=\"color:#66d9ef\">string<\/span>]<span style=\"color:#f92672\">:<\/span> <span style=\"color:#a6e22e\">ActionReducer<\/span>&lt;<span style=\"color:#f92672\">any<\/span><span style=\"color:#960050;background-color:#1e0010\">,<\/span> <span style=\"color:#a6e22e\">any<\/span>&gt; }) {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">reducers<\/span> <span style=\"color:#f92672\">=<\/span> { ...<span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">reducers<\/span>, ...<span style=\"color:#a6e22e\">reducers<\/span> };\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">updateReducers<\/span>(Object.<span style=\"color:#a6e22e\">keys<\/span>(<span style=\"color:#a6e22e\">reducers<\/span>));\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">updateReducers<\/span>(<span style=\"color:#a6e22e\">featureKeys<\/span>: <span style=\"color:#66d9ef\">string<\/span>[]) {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">next<\/span>(<span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">reducerFactory<\/span>(<span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">reducers<\/span>, <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">initialState<\/span>));\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#75715e\">\/* ... *\/<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p><code>this.next(this.reducerFactory(this.reducers, this.initialState))<\/code> will make sure that whenever actions are dispatched, the reducer of each slice will be invoked(including the new slices added). This is how the store is kept update to date every time a new feature is added\/removed.<\/p>\n<p><strong>That&rsquo;s it, folks! Thanks for reading!<\/strong><\/p>\n"},{"title":"A thorough exploration of Angular Forms","link":"https:\/\/andreigatej.dev\/blog\/a-thorough-exploration-of-angular-forms\/","pubDate":"Fri, 14 Feb 2020 00:00:00 +0000","guid":"https:\/\/andreigatej.dev\/blog\/a-thorough-exploration-of-angular-forms\/","description":"<p><em>This article has been published on <a href=\"https:\/\/indepth.dev\/posts\/1143\/a-thorough-exploration-of-angular-forms\" target=\"_blank\" rel=\"noopener\">indepth.dev<\/a>.<\/em><\/p>\n<h2 id=\"introduction\">\n  <span>\n  Introduction\n  <\/span>\n  <a href=\"#introduction\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><p>After delving into the <code>@angular\/forms<\/code> package, I&rsquo;ve been able to get a better understanding of how things really work under the hood. In this article I&rsquo;d like to share my vision with you.<\/p>\n<h2 id=\"base-entities\">\n  <span>\n  Base entities\n  <\/span>\n  <a href=\"#base-entities\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><p>In order to get the most out of the <strong>Forms API<\/strong>, we must ensure that we look over some of its essential parts.<\/p>\n<h3 id=\"abstractcontrol\">\n  <span>\n  AbstractControl\n  <\/span>\n  <a href=\"#abstractcontrol\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h3><p>This (abstract) class contains logic shared across <code>FormControl<\/code>, <code>FormGroup<\/code> and <code>FormArray<\/code>:<\/p>\n<ul>\n<li>running validators<\/li>\n<li>changing and calculating UI status - <code>markAsDirty()<\/code>, <code>markAsTouched()<\/code>, <code>dirty<\/code>, <code>touched<\/code>, <code>pristine<\/code> etc&hellip;<\/li>\n<li>resetting status<\/li>\n<li>keeping track of validation status(<code>invalid<\/code>, <code>valid<\/code>)<\/li>\n<\/ul>\n<p>This class, as well as its subclasses, can referred to as the <strong>model layer<\/strong> - it stores data related to a specific entity.<\/p>\n<p>Multiple <code>AbstractControl<\/code>s can be seen as tree where the leaves are always going to be <code>FormControl<\/code> instances and the other 2 (<code>FormArray<\/code>, <code>FormGroup<\/code>) can be thought of as <code>AbstractControl<\/code> containers, which entails that they can&rsquo;t be used as leaves because they must contain at least on <code>AbstractControl<\/code> instance.<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-markdown\" data-lang=\"markdown\"><span style=\"display:flex;\"><span>\/\/ FG - FormGroup\n<\/span><\/span><span style=\"display:flex;\"><span>\/\/ FA - FormArray\n<\/span><\/span><span style=\"display:flex;\"><span>\/\/ FC - FormControl\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>    FG\n<\/span><\/span><span style=\"display:flex;\"><span>  \/   \\\n<\/span><\/span><span style=\"display:flex;\"><span>FC    FG\n<\/span><\/span><span style=\"display:flex;\"><span>    \/    \\\n<\/span><\/span><span style=\"display:flex;\"><span>  FC     FA\n<\/span><\/span><span style=\"display:flex;\"><span>        \/ | \\\n<\/span><\/span><span style=\"display:flex;\"><span>      FC FC FC\n<\/span><\/span><\/code><\/pre><\/div><p>The above tree can be the result of:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-html\" data-lang=\"html\"><span style=\"display:flex;\"><span>&lt;<span style=\"color:#f92672\">form<\/span>&gt;\n<\/span><\/span><span style=\"display:flex;\"><span>  &lt;<span style=\"color:#f92672\">input<\/span> <span style=\"color:#a6e22e\">type<\/span><span style=\"color:#f92672\">=<\/span><span style=\"color:#e6db74\">&#34;text&#34;<\/span> <span style=\"color:#a6e22e\">formControlName<\/span><span style=\"color:#f92672\">=<\/span><span style=\"color:#e6db74\">&#34;companyName&#34;<\/span>&gt;\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>  &lt;<span style=\"color:#f92672\">ng-container<\/span> <span style=\"color:#a6e22e\">formGroupName<\/span><span style=\"color:#f92672\">=<\/span><span style=\"color:#e6db74\">&#34;personal&#34;<\/span>&gt;\n<\/span><\/span><span style=\"display:flex;\"><span>    &lt;<span style=\"color:#f92672\">input<\/span> <span style=\"color:#a6e22e\">type<\/span><span style=\"color:#f92672\">=<\/span><span style=\"color:#e6db74\">&#34;text&#34;<\/span> <span style=\"color:#a6e22e\">formControlName<\/span><span style=\"color:#f92672\">=<\/span><span style=\"color:#e6db74\">&#34;name&#34;<\/span>&gt;\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>    &lt;<span style=\"color:#f92672\">ng-container<\/span> <span style=\"color:#a6e22e\">formArrayName<\/span><span style=\"color:#f92672\">=<\/span><span style=\"color:#e6db74\">&#34;hobbies&#34;<\/span>&gt;\n<\/span><\/span><span style=\"display:flex;\"><span>      &lt;<span style=\"color:#f92672\">input<\/span> <span style=\"color:#a6e22e\">type<\/span><span style=\"color:#f92672\">=<\/span><span style=\"color:#e6db74\">&#34;checkbox&#34;<\/span> <span style=\"color:#a6e22e\">formControlName<\/span><span style=\"color:#f92672\">=<\/span><span style=\"color:#e6db74\">&#34;0&#34;<\/span>&gt;\n<\/span><\/span><span style=\"display:flex;\"><span>      &lt;<span style=\"color:#f92672\">input<\/span> <span style=\"color:#a6e22e\">type<\/span><span style=\"color:#f92672\">=<\/span><span style=\"color:#e6db74\">&#34;checkbox&#34;<\/span> <span style=\"color:#a6e22e\">formControlName<\/span><span style=\"color:#f92672\">=<\/span><span style=\"color:#e6db74\">&#34;1&#34;<\/span>&gt;\n<\/span><\/span><span style=\"display:flex;\"><span>      &lt;<span style=\"color:#f92672\">input<\/span> <span style=\"color:#a6e22e\">type<\/span><span style=\"color:#f92672\">=<\/span><span style=\"color:#e6db74\">&#34;checkbox&#34;<\/span> <span style=\"color:#a6e22e\">formControlName<\/span><span style=\"color:#f92672\">=<\/span><span style=\"color:#e6db74\">&#34;2&#34;<\/span>&gt;\n<\/span><\/span><span style=\"display:flex;\"><span>    &lt;\/<span style=\"color:#f92672\">ng-container<\/span>&gt;\n<\/span><\/span><span style=\"display:flex;\"><span>  &lt;\/<span style=\"color:#f92672\">ng-container<\/span>&gt;\n<\/span><\/span><span style=\"display:flex;\"><span>&lt;\/<span style=\"color:#f92672\">form<\/span>&gt;\n<\/span><\/span><\/code><\/pre><\/div><p>You can find more about <code>formArrayName<\/code> and <code>formGroupName<\/code> in the upcoming sections.<\/p>\n<h3 id=\"formcontrol\">\n  <span>\n  FormControl\n  <\/span>\n  <a href=\"#formcontrol\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h3><p>It extends <code>AbstractControl<\/code>, which means it will inherit all the characteristics listed above. What&rsquo;s important to mention here is that <code>FormControl<\/code> is put together with <strong>only one<\/strong> form control(a <strong>DOM element:<\/strong> <code>&lt;input&gt;<\/code>, <code>&lt;textarea&gt;<\/code>) or a custom component(with the help of <code>ControlValueAccessor<\/code> - more on that later!).<\/p>\n<p>A <code>FormControl<\/code> can be considered <strong>standalone<\/strong> if it <strong>does not belong<\/strong> to an <code>AbstractControl<\/code> tree. As a result, it will be <strong>completely<\/strong> independent, meaning that its validity, value and user interaction won&rsquo;t be affect any of its <strong>form container ancestors<\/strong>(<a href=\"https:\/\/ng-run.com\/edit\/Xx0irFLVo4FdueEBtSAF?open=app%2Fexample-standalone.component.ts\" target=\"_blank\" rel=\"noopener\">ng-run Example<\/a>).<\/p>\n<h3 id=\"formarray\">\n  <span>\n  FormArray\n  <\/span>\n  <a href=\"#formarray\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h3><p>It extends <code>AbstractControl<\/code> and its job is to group multiple <code>AbstractControls<\/code> together.<\/p>\n<p>From a tree perspective, it is a node that must contain at least one descendant. Its <strong>validation status<\/strong>, <strong>dirtiness<\/strong>, <strong>touched status<\/strong> and <strong>value<\/strong> usually depend on its descendants. There could be cases, though, where a container has certain validators so errors might appear at that node&rsquo;s level.<\/p>\n<p>Its defining characteristic is that it stores its children in an <strong>array<\/strong>.<\/p>\n<h3 id=\"formgroup\">\n  <span>\n  FormGroup\n  <\/span>\n  <a href=\"#formgroup\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h3><p>Same as <code>FormArray<\/code>, except that it stores its descendants in an <strong>object<\/strong>.<\/p>\n<h3 id=\"abstractcontroldirective\">\n  <span>\n  AbstractControlDirective\n  <\/span>\n  <a href=\"#abstractcontroldirective\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h3><p>It is the base class for <strong>form-control-based directives(<\/strong><code>NgModel<\/code>, <code>FormControlName<\/code>, <code>FormControlDirective<\/code>) and contains <strong>boolean getters<\/strong> that reflect the current status of the bound control(<code>valid<\/code>, <code>touched<\/code>, <code>dirty<\/code> etc&hellip;).\nThe previously mentioned control is bound to a <strong>DOM element<\/strong> with the help of a concrete implementation of <code>AbstractControlDirective<\/code>(<code>NgModel<\/code>, <code>FormControlName<\/code>) and a <code>ControlValueAccessor<\/code>.<\/p>\n<p>Thus, this class can be thought of as a <strong>middleman<\/strong> that connects <code>ControlValueAccessor<\/code>(<strong>view layer<\/strong>) with <code>AbstractControl<\/code>(<strong>model layer<\/strong>) - more on that in the forthcoming sections.<\/p>\n<p>It is worth mentioning that multiple <code>AbstractControlDirectives<\/code> can bind the same <code>AbstractControl<\/code> to multiple <strong>DOM elements or custom components,<\/strong> to multiple <code>ControlValueAccessors<\/code>.<\/p>\n<p>Consider this example:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-html\" data-lang=\"html\"><span style=\"display:flex;\"><span>&lt;<span style=\"color:#f92672\">form<\/span>&gt;\n<\/span><\/span><span style=\"display:flex;\"><span>  &lt;<span style=\"color:#f92672\">input<\/span> <span style=\"color:#a6e22e\">ngModel<\/span> <span style=\"color:#a6e22e\">name<\/span><span style=\"color:#f92672\">=<\/span><span style=\"color:#e6db74\">&#34;option&#34;<\/span> <span style=\"color:#a6e22e\">value<\/span><span style=\"color:#f92672\">=<\/span><span style=\"color:#e6db74\">&#34;value1&#34;<\/span> <span style=\"color:#a6e22e\">type<\/span><span style=\"color:#f92672\">=<\/span><span style=\"color:#e6db74\">&#34;radio&#34;<\/span>&gt;\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>  &lt;<span style=\"color:#f92672\">input<\/span> <span style=\"color:#a6e22e\">ngModel<\/span><span style=\"color:#f92672\">=<\/span><span style=\"color:#e6db74\">&#34;value3&#34;<\/span> <span style=\"color:#a6e22e\">name<\/span><span style=\"color:#f92672\">=<\/span><span style=\"color:#e6db74\">&#34;option&#34;<\/span> <span style=\"color:#a6e22e\">value<\/span><span style=\"color:#f92672\">=<\/span><span style=\"color:#e6db74\">&#34;value2&#34;<\/span> <span style=\"color:#a6e22e\">type<\/span><span style=\"color:#f92672\">=<\/span><span style=\"color:#e6db74\">&#34;radio&#34;<\/span>&gt;\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>  &lt;<span style=\"color:#f92672\">input<\/span> <span style=\"color:#a6e22e\">ngModel<\/span><span style=\"color:#f92672\">=<\/span><span style=\"color:#e6db74\">&#34;value1&#34;<\/span> <span style=\"color:#a6e22e\">name<\/span><span style=\"color:#f92672\">=<\/span><span style=\"color:#e6db74\">&#34;option&#34;<\/span> <span style=\"color:#a6e22e\">value<\/span><span style=\"color:#f92672\">=<\/span><span style=\"color:#e6db74\">&#34;value3&#34;<\/span> <span style=\"color:#a6e22e\">type<\/span><span style=\"color:#f92672\">=<\/span><span style=\"color:#e6db74\">&#34;radio&#34;<\/span>&gt;\n<\/span><\/span><span style=\"display:flex;\"><span>&lt;\/<span style=\"color:#f92672\">form<\/span>&gt;\n<\/span><\/span><\/code><\/pre><\/div><p>As a side note, providing a default value right from the template can be achieved by setting the last <code>ngModel<\/code> directive&rsquo;s value to the value of the radio button you want to be checked by default. In the above snippet, the first button will be checked.<\/p>\n<p>This happens because the last directive will be the one which will have the <em>final<\/em> call of the <code>setUpControl()<\/code> function:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-tsx\" data-lang=\"tsx\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">export<\/span> <span style=\"color:#66d9ef\">function<\/span> <span style=\"color:#a6e22e\">setUpControl<\/span>(<span style=\"color:#a6e22e\">control<\/span>: <span style=\"color:#66d9ef\">FormControl<\/span>, <span style=\"color:#a6e22e\">dir<\/span>: <span style=\"color:#66d9ef\">NgControl<\/span>)<span style=\"color:#f92672\">:<\/span> <span style=\"color:#66d9ef\">void<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#f92672\">!<\/span><span style=\"color:#a6e22e\">control<\/span>) <span style=\"color:#a6e22e\">_throwError<\/span>(<span style=\"color:#a6e22e\">dir<\/span>, <span style=\"color:#e6db74\">&#39;Cannot find control with&#39;<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#f92672\">!<\/span><span style=\"color:#a6e22e\">dir<\/span>.<span style=\"color:#a6e22e\">valueAccessor<\/span>) <span style=\"color:#a6e22e\">_throwError<\/span>(<span style=\"color:#a6e22e\">dir<\/span>, <span style=\"color:#e6db74\">&#39;No value accessor for form control with&#39;<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#75715e\">\/* ... *\/<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">dir<\/span>.<span style=\"color:#a6e22e\">valueAccessor<\/span> <span style=\"color:#f92672\">!<\/span>.<span style=\"color:#a6e22e\">writeValue<\/span>(<span style=\"color:#a6e22e\">control<\/span>.<span style=\"color:#a6e22e\">value<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>  \n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#75715e\">\/* ... *\/<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p><a href=\"https:\/\/ng-run.com\/edit\/Xx0irFLVo4FdueEBtSAF?open=app%2Fradio-example.component.ts\" target=\"_blank\" rel=\"noopener\"><em>ng-run Example.<\/em><\/a><\/p>\n<h3 id=\"abstractformgroupdirective\">\n  <span>\n  AbstractFormGroupDirective\n  <\/span>\n  <a href=\"#abstractformgroupdirective\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h3><p>It&rsquo;s a container for <code>AbstractFormGroupDirective<\/code> and <code>AbstractControlDirective<\/code> instances and its useful when you want to create a sub-group of <code>AbstractControls<\/code>(e.g. <code>address: { city, street, zipcode }<\/code>) or run validators for some specific <code>AbstractControl<\/code>s(e.g: <em>min-max<\/em> validator that makes sure that <em>min<\/em> control can&rsquo;t have a value that is greater than <em>max<\/em> control&rsquo;s value).<\/p>\n<p>Its concrete implementations are: <code>formGroupName<\/code>, <code>formArrayName<\/code>, <code>ngModelGroup<\/code>.<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-html\" data-lang=\"html\"><span style=\"display:flex;\"><span>&lt;<span style=\"color:#f92672\">form<\/span> <span style=\"color:#960050;background-color:#1e0010\">[<\/span><span style=\"color:#a6e22e\">formGroup<\/span><span style=\"color:#960050;background-color:#1e0010\">]=&#34;<\/span><span style=\"color:#a6e22e\">filterForm<\/span><span style=\"color:#960050;background-color:#1e0010\">&#34;<\/span>&gt;\n<\/span><\/span><span style=\"display:flex;\"><span>  &lt;<span style=\"color:#f92672\">ng-container<\/span> <span style=\"color:#a6e22e\">formGroupName<\/span><span style=\"color:#f92672\">=<\/span><span style=\"color:#e6db74\">&#34;price&#34;<\/span>&gt;\n<\/span><\/span><span style=\"display:flex;\"><span>    &lt;<span style=\"color:#f92672\">input<\/span> <span style=\"color:#a6e22e\">formControlName<\/span><span style=\"color:#f92672\">=<\/span><span style=\"color:#e6db74\">&#34;min&#34;<\/span> <span style=\"color:#a6e22e\">type<\/span><span style=\"color:#f92672\">=<\/span><span style=\"color:#e6db74\">&#34;text&#34;<\/span>&gt;\n<\/span><\/span><span style=\"display:flex;\"><span>    &lt;<span style=\"color:#f92672\">input<\/span> <span style=\"color:#a6e22e\">formControlName<\/span><span style=\"color:#f92672\">=<\/span><span style=\"color:#e6db74\">&#34;max&#34;<\/span> <span style=\"color:#a6e22e\">type<\/span><span style=\"color:#f92672\">=<\/span><span style=\"color:#e6db74\">&#34;text&#34;<\/span>&gt;\n<\/span><\/span><span style=\"display:flex;\"><span>  &lt;\/<span style=\"color:#f92672\">ng-container<\/span>&gt;\n<\/span><\/span><span style=\"display:flex;\"><span>&lt;\/<span style=\"color:#f92672\">form<\/span>&gt;\n<\/span><\/span><\/code><\/pre><\/div><p><code>FormGroupName<\/code>, being a subclass of <code>AbstractFormGroupDirective<\/code>, it has all the attributes listed at the beginning of this section. It acts as a container for <code>AbstractControl<\/code> instances as well. But, <code>FormGroup<\/code> can only be the top-level container. This means, you can&rsquo;t use <code>FormGroupName<\/code> as a top-level container as it will result in an error.<\/p>\n<p><code>AbstractFormGroupDirective<\/code> provides a way to access to top level <code>FormGroup<\/code> instance:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-tsx\" data-lang=\"tsx\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">get<\/span> <span style=\"color:#a6e22e\">formDirective<\/span>()<span style=\"color:#f92672\">:<\/span> <span style=\"color:#a6e22e\">Form<\/span><span style=\"color:#f92672\">|<\/span><span style=\"color:#66d9ef\">null<\/span> { <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">_parent<\/span> <span style=\"color:#f92672\">?<\/span> <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">_parent.formDirective<\/span> : <span style=\"color:#66d9ef\">null<\/span>; }\n<\/span><\/span><\/code><\/pre><\/div><p>where <code>this._parent<\/code> can be another <code>AbstractFormGroupDirective<\/code> or a <code>FormGroupDirective<\/code> instance. The <code>FormGroupDirective<\/code> does not have a _parent property.<\/p>\n<h2 id=\"controlvalueaccessor\">\n  <span>\n  ControlValueAccessor\n  <\/span>\n  <a href=\"#controlvalueaccessor\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><p><code>ControlValueAccessor<\/code> is an essential part for the <strong>Forms API<\/strong> and can be thought of as the <strong>view layer<\/strong>.<\/p>\n<p>Its job is to connect a **DOM element(**e.g. <code>&lt;input&gt;<\/code>, <code>&lt;textarea&gt;<\/code>) or a custom component(e.g. <code>&lt;app-custom-input&gt;<\/code>) with an <code>AbstractControlDirective<\/code>(e.g. <code>NgModel<\/code>, <code>FormControlName<\/code>). <code>AbstractControlDirective<\/code> will eventually become a bridge between <code>ControlValueAccessor<\/code>(<strong>view layer<\/strong>) and <code>AbstractControl<\/code>(<strong>model layer<\/strong>).\nThis way, the 2 layers can interact with each other.<\/p>\n<p>For instance:<\/p>\n<ul>\n<li>when user is typing into an input: <code>View<\/code> -&gt; <code>Model<\/code><\/li>\n<li>when the value is set programmatically(<code>FormControl.setValue('newValue')<\/code>): <code>Model<\/code> -&gt; <code>View<\/code><\/li>\n<\/ul>\n<p>Only <code>FormControl<\/code> instances can <em>directly<\/em> interact with a <code>ControlValueAccessor<\/code>, because, in a tree of <code>AbstractControls<\/code>, a <code>FormControl<\/code> can only be the leaf node as it is not supposed to contain other nodes. Along these lines, we can deduce that <strong>updates<\/strong> that come <strong>from the view<\/strong> will <strong>start from leaf<\/strong> nodes.<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-markdown\" data-lang=\"markdown\"><span style=\"display:flex;\"><span>\/\/ FG - FormGroup\n<\/span><\/span><span style=\"display:flex;\"><span>\/\/ FA - FormArray\n<\/span><\/span><span style=\"display:flex;\"><span>\/\/ FC - FormControl\n<\/span><\/span><span style=\"display:flex;\"><span>                                  FG\n<\/span><\/span><span style=\"display:flex;\"><span>                                \/   \\\n<\/span><\/span><span style=\"display:flex;\"><span>user typing into an input  &lt;<span style=\"color:#f92672\">-<\/span> <span style=\"color:#a6e22e\">FC<\/span>    <span style=\"color:#a6e22e\">FA<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>                                   <span style=\"color:#960050;background-color:#1e0010\">\/<\/span> <span style=\"color:#960050;background-color:#1e0010\">|<\/span> <span style=\"color:#960050;background-color:#1e0010\">\\<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>                                <span style=\"color:#a6e22e\">FC<\/span>  <span style=\"color:#a6e22e\">FC<\/span>  <span style=\"color:#a6e22e\">FC<\/span> <span style=\"color:#960050;background-color:#1e0010\">&lt;<\/span><span style=\"color:#a6e22e\">-<\/span> <span style=\"color:#a6e22e\">user<\/span> <span style=\"color:#a6e22e\">selecting<\/span> <span style=\"color:#a6e22e\">checkbox<\/span>\n<\/span><\/span><\/code><\/pre><\/div><p>The <code>ControlValueAccessor<\/code> interface looks like this:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-tsx\" data-lang=\"tsx\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">export<\/span> <span style=\"color:#66d9ef\">interface<\/span> <span style=\"color:#a6e22e\">ControlValueAccessor<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">writeValue<\/span>(<span style=\"color:#a6e22e\">obj<\/span>: <span style=\"color:#66d9ef\">any<\/span>)<span style=\"color:#f92672\">:<\/span> <span style=\"color:#66d9ef\">void<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">registerOnChange<\/span>(<span style=\"color:#a6e22e\">fn<\/span>: <span style=\"color:#66d9ef\">any<\/span>)<span style=\"color:#f92672\">:<\/span> <span style=\"color:#66d9ef\">void<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">registerOnTouched<\/span>(<span style=\"color:#a6e22e\">fn<\/span>: <span style=\"color:#66d9ef\">any<\/span>)<span style=\"color:#f92672\">:<\/span> <span style=\"color:#66d9ef\">void<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">setDisabledState<\/span><span style=\"color:#f92672\">?<\/span>(<span style=\"color:#a6e22e\">isDisabled<\/span>: <span style=\"color:#66d9ef\">boolean<\/span>)<span style=\"color:#f92672\">:<\/span> <span style=\"color:#66d9ef\">void<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><ul>\n<li><code>writeValue()<\/code> - writes a new value to an element; the new value comes from the <strong>MODEL<\/strong>(<code>FormControl.setValue<\/code> -&gt; <code>ControlValueAccessor.writeValue<\/code> -&gt; update element -&gt; change is visible in the <strong>UI<\/strong>)<\/li>\n<li><code>registerOnChange()<\/code> - registers a <strong>callback function<\/strong> that will be called whenever the value <strong>changes<\/strong> in the <strong>UI<\/strong> and will <strong>propagate<\/strong> the new value to the model.<\/li>\n<li><code>registerOnTouched()<\/code> - registers a <strong>callback function<\/strong> that will be called when the <strong>blur<\/strong> event occurs; the <code>FormControl<\/code> will be notified of this event as it may need to perform some updates when this event occurs.<\/li>\n<li><code>setDisabledState()<\/code> - will <strong>disable\/enable<\/strong> the <strong>DOM element<\/strong> depending on the value provided; this method is usually called as a result of a change in the <strong>MODEL<\/strong>.<\/li>\n<\/ul>\n<p>You can see these methods&rsquo; usefulness in the following section: <a href=\"#connecting-formcontrol-with-controlvalueaccessor\"><em>Connecting <code>FormControl<\/code> with <code>ControlValueAccessor<\/code><\/em><\/a>.<\/p>\n<p>There are 3 types of <code>ControlValueAccessors<\/code>:<\/p>\n<p>default<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-tsx\" data-lang=\"tsx\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">@Directive<\/span>({\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">selector<\/span><span style=\"color:#f92672\">:<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#e6db74\">&#39;input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]&#39;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>})\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">export<\/span> <span style=\"color:#66d9ef\">class<\/span> <span style=\"color:#a6e22e\">DefaultValueAccessor<\/span> <span style=\"color:#66d9ef\">implements<\/span> <span style=\"color:#a6e22e\">ControlValueAccessor<\/span> { }\n<\/span><\/span><\/code><\/pre><\/div><p>built-in<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-tsx\" data-lang=\"tsx\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">BUILTIN_ACCESSORS<\/span> <span style=\"color:#f92672\">=<\/span> [\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">CheckboxControlValueAccessor<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">RangeValueAccessor<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">NumberValueAccessor<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">SelectControlValueAccessor<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">SelectMultipleControlValueAccessor<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">RadioControlValueAccessor<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>];\n<\/span><\/span><\/code><\/pre><\/div><p>You can read more about built-in accessors in <a href=\"#exploring-built-in-controlvalueaccessors\"><em>Exploring built-in <code>ControlValueAccessors<\/code><\/em><\/a>.<\/p>\n<p>custom - when you want a custom component to be part of the <code>AbstractControl<\/code> tree<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-tsx\" data-lang=\"tsx\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">@Component<\/span>({\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">selector<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;app-custom-component&#39;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">providers<\/span><span style=\"color:#f92672\">:<\/span> [\n<\/span><\/span><span style=\"display:flex;\"><span>    {\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#a6e22e\">provide<\/span>: <span style=\"color:#66d9ef\">NG_VALUE_ACCESSOR<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#a6e22e\">useExisting<\/span>: <span style=\"color:#66d9ef\">CustomInputComponent<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#a6e22e\">multi<\/span>: <span style=\"color:#66d9ef\">true<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>    }\n<\/span><\/span><span style=\"display:flex;\"><span>  ]\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#75715e\">\/* ... *\/<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>})\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">export<\/span> <span style=\"color:#66d9ef\">class<\/span> <span style=\"color:#a6e22e\">CustomInputComponent<\/span> <span style=\"color:#66d9ef\">implements<\/span> <span style=\"color:#a6e22e\">ControlValueAccessor<\/span> { }\n<\/span><\/span><\/code><\/pre><\/div><div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-html\" data-lang=\"html\"><span style=\"display:flex;\"><span>&lt;<span style=\"color:#f92672\">form<\/span>&gt;\n<\/span><\/span><span style=\"display:flex;\"><span>  &lt;<span style=\"color:#f92672\">app-custom-component<\/span> <span style=\"color:#a6e22e\">ngModel<\/span> <span style=\"color:#a6e22e\">name<\/span><span style=\"color:#f92672\">=<\/span><span style=\"color:#e6db74\">&#34;name&#34;<\/span>&gt;&lt;\/<span style=\"color:#f92672\">app-custom-component<\/span>&gt;\n<\/span><\/span><span style=\"display:flex;\"><span>&lt;\/<span style=\"color:#f92672\">form<\/span>&gt;\n<\/span><\/span><\/code><\/pre><\/div><p>Remember that <code>ngModel<\/code> is a <strong>form-control-based<\/strong> directive, so it will become a bridge between a <code>ControlValueAccessor<\/code>(<strong>view<\/strong>) and <code>FormControl<\/code>(<strong>model<\/strong>).<\/p>\n<h2 id=\"connecting-formcontrol-with-controlvalueaccessor\">\n  <span>\n  Connecting <code>FormControl<\/code> with <code>ControlValueAccessor<\/code>\n  <\/span>\n  <a href=\"#connecting-formcontrol-with-controlvalueaccessor\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><p>As mentioned in the previous sections, <code>AbstractControlDirective<\/code> is what the <strong>view layer<\/strong>(<code>ControlValueAccessor<\/code>) needs in order to effectively communicate with the <strong>model layer<\/strong>(<code>AbstractControl<\/code>, concretely <code>FormControl<\/code>) and vice versa.<\/p>\n<p>This connection can be visualized like as follows:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-markdown\" data-lang=\"markdown\"><span style=\"display:flex;\"><span>--------------------------\u2008\n<\/span><\/span><span style=\"display:flex;\"><span>  |                        |\u2008\n<\/span><\/span><span style=\"display:flex;\"><span>  |  ControlValueAccessor  |\u2008 &lt;<span style=\"color:#f92672\">---<\/span> <span style=\"color:#a6e22e\">View<\/span> <span style=\"color:#a6e22e\">Layer<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#960050;background-color:#1e0010\">|<\/span>                        <span style=\"color:#960050;background-color:#1e0010\">|<\/span>\u2008\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">--------------------------<\/span>\u2008\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#960050;background-color:#1e0010\">|<\/span>                 <span style=\"color:#960050;background-color:#1e0010\">\u25b2<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#960050;background-color:#1e0010\">|<\/span>                 <span style=\"color:#960050;background-color:#1e0010\">|<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#960050;background-color:#1e0010\">|<\/span>                 <span style=\"color:#960050;background-color:#1e0010\">|<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#960050;background-color:#1e0010\">\u25bc<\/span>                 <span style=\"color:#960050;background-color:#1e0010\">|<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">------------------------------<\/span>\u2008\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#960050;background-color:#1e0010\">|<\/span>                            <span style=\"color:#960050;background-color:#1e0010\">|<\/span>\u2008\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#960050;background-color:#1e0010\">|<\/span>  <span style=\"color:#a6e22e\">AbstractControlDirective<\/span>  <span style=\"color:#960050;background-color:#1e0010\">|<\/span>\u2008\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#960050;background-color:#1e0010\">|<\/span>                            <span style=\"color:#960050;background-color:#1e0010\">|<\/span>\u2008\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">------------------------------<\/span>\u2008\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#960050;background-color:#1e0010\">|<\/span>           <span style=\"color:#960050;background-color:#1e0010\">\u25b2<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#960050;background-color:#1e0010\">|<\/span>           <span style=\"color:#960050;background-color:#1e0010\">|<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#960050;background-color:#1e0010\">|<\/span>           <span style=\"color:#960050;background-color:#1e0010\">|<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#960050;background-color:#1e0010\">\u25bc<\/span>           <span style=\"color:#960050;background-color:#1e0010\">|<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#a6e22e\">-----------------<\/span>\u2008\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#960050;background-color:#1e0010\">|<\/span>               <span style=\"color:#960050;background-color:#1e0010\">|<\/span>\u2008\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#960050;background-color:#1e0010\">|<\/span>  <span style=\"color:#a6e22e\">FormControl<\/span>  <span style=\"color:#960050;background-color:#1e0010\">|<\/span>\u2008 <span style=\"color:#960050;background-color:#1e0010\">&lt;<\/span><span style=\"color:#a6e22e\">---<\/span> <span style=\"color:#a6e22e\">Model<\/span> <span style=\"color:#a6e22e\">Layer<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#960050;background-color:#1e0010\">|<\/span>               <span style=\"color:#960050;background-color:#1e0010\">|<\/span>\u2008\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#a6e22e\">-----------------<\/span>\n<\/span><\/span><\/code><\/pre><\/div><p>The <code>\u2193<\/code> indicates the <strong>ViewToModelPipeline<\/strong>, whereas <code>\u2191<\/code> indicates the <strong>ModelToViewPipeline<\/strong>.<\/p>\n<p><code>AbstractControlDirective<\/code> plays a critical role here. Let&rsquo;s examine the actual implementation!<\/p>\n<p>The above diagram is the result of this code snippet:<\/p>\n<blockquote>\n<p>In reality, <code>NgControl<\/code> extends <code>AbstractControlDirective<\/code> and it mainly acts as a provider for <strong>form-control-based<\/strong> directives: <code>NgModel<\/code>, <code>FormControlName<\/code> etc&hellip;, but doesn&rsquo;t have any default implementation.<\/p>\n<\/blockquote>\n<p>The <code>setUpControl<\/code> function is <strong>called<\/strong> every time a <strong>form-control-based<\/strong> directive is <strong>initialized<\/strong>.<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-tsx\" data-lang=\"tsx\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">export<\/span> <span style=\"color:#66d9ef\">function<\/span> <span style=\"color:#a6e22e\">setUpControl<\/span>(<span style=\"color:#a6e22e\">control<\/span>: <span style=\"color:#66d9ef\">FormControl<\/span>, <span style=\"color:#a6e22e\">dir<\/span>: <span style=\"color:#66d9ef\">NgControl<\/span>)<span style=\"color:#f92672\">:<\/span> <span style=\"color:#66d9ef\">void<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#f92672\">!<\/span><span style=\"color:#a6e22e\">control<\/span>) <span style=\"color:#a6e22e\">_throwError<\/span>(<span style=\"color:#a6e22e\">dir<\/span>, <span style=\"color:#e6db74\">&#39;Cannot find control with&#39;<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#f92672\">!<\/span><span style=\"color:#a6e22e\">dir<\/span>.<span style=\"color:#a6e22e\">valueAccessor<\/span>) <span style=\"color:#a6e22e\">_throwError<\/span>(<span style=\"color:#a6e22e\">dir<\/span>, <span style=\"color:#e6db74\">&#39;No value accessor for form control with&#39;<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">control<\/span>.<span style=\"color:#a6e22e\">validator<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">Validators<\/span>.<span style=\"color:#a6e22e\">compose<\/span>([<span style=\"color:#a6e22e\">control<\/span>.<span style=\"color:#a6e22e\">validator<\/span> <span style=\"color:#f92672\">!<\/span>, <span style=\"color:#a6e22e\">dir<\/span>.<span style=\"color:#a6e22e\">validator<\/span>]);\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">control<\/span>.<span style=\"color:#a6e22e\">asyncValidator<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">Validators<\/span>.<span style=\"color:#a6e22e\">composeAsync<\/span>([<span style=\"color:#a6e22e\">control<\/span>.<span style=\"color:#a6e22e\">asyncValidator<\/span> <span style=\"color:#f92672\">!<\/span>, <span style=\"color:#a6e22e\">dir<\/span>.<span style=\"color:#a6e22e\">asyncValidator<\/span>]);\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">dir<\/span>.<span style=\"color:#a6e22e\">valueAccessor<\/span> <span style=\"color:#f92672\">!<\/span>.<span style=\"color:#a6e22e\">writeValue<\/span>(<span style=\"color:#a6e22e\">control<\/span>.<span style=\"color:#a6e22e\">value<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">setUpViewChangePipeline<\/span>(<span style=\"color:#a6e22e\">control<\/span>, <span style=\"color:#a6e22e\">dir<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">setUpModelChangePipeline<\/span>(<span style=\"color:#a6e22e\">control<\/span>, <span style=\"color:#a6e22e\">dir<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">setUpBlurPipeline<\/span>(<span style=\"color:#a6e22e\">control<\/span>, <span style=\"color:#a6e22e\">dir<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#75715e\">\/* ... Skipped for brevity ... *\/<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ VIEW -&gt; MODEL\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span><span style=\"color:#66d9ef\">function<\/span> <span style=\"color:#a6e22e\">setUpViewChangePipeline<\/span>(<span style=\"color:#a6e22e\">control<\/span>: <span style=\"color:#66d9ef\">FormControl<\/span>, <span style=\"color:#a6e22e\">dir<\/span>: <span style=\"color:#66d9ef\">NgControl<\/span>)<span style=\"color:#f92672\">:<\/span> <span style=\"color:#66d9ef\">void<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">dir<\/span>.<span style=\"color:#a6e22e\">valueAccessor<\/span> <span style=\"color:#f92672\">!<\/span>.<span style=\"color:#a6e22e\">registerOnChange<\/span>((<span style=\"color:#a6e22e\">newValue<\/span>: <span style=\"color:#66d9ef\">any<\/span>) <span style=\"color:#f92672\">=&gt;<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">control<\/span>.<span style=\"color:#a6e22e\">_pendingValue<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">newValue<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">control<\/span>.<span style=\"color:#a6e22e\">_pendingChange<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">true<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">control<\/span>.<span style=\"color:#a6e22e\">_pendingDirty<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">true<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#a6e22e\">control<\/span>.<span style=\"color:#a6e22e\">updateOn<\/span> <span style=\"color:#f92672\">===<\/span> <span style=\"color:#e6db74\">&#39;change&#39;<\/span>) <span style=\"color:#a6e22e\">updateControl<\/span>(<span style=\"color:#a6e22e\">control<\/span>, <span style=\"color:#a6e22e\">dir<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>  });\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ Update the MODEL based on the VIEW&#39;s value\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span><span style=\"color:#66d9ef\">function<\/span> <span style=\"color:#a6e22e\">updateControl<\/span>(<span style=\"color:#a6e22e\">control<\/span>: <span style=\"color:#66d9ef\">FormControl<\/span>, <span style=\"color:#a6e22e\">dir<\/span>: <span style=\"color:#66d9ef\">NgControl<\/span>)<span style=\"color:#f92672\">:<\/span> <span style=\"color:#66d9ef\">void<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#a6e22e\">control<\/span>.<span style=\"color:#a6e22e\">_pendingDirty<\/span>) <span style=\"color:#a6e22e\">control<\/span>.<span style=\"color:#a6e22e\">markAsDirty<\/span>();\n<\/span><\/span><span style=\"display:flex;\"><span>  \n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#75715e\">\/\/ `{emitModelToViewChange: false}` will make sure that `ControlValueAccessor.writeValue` won&#39;t be called\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>  <span style=\"color:#75715e\">\/\/ again since the value is already updated, because this change comes from the view\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>  <span style=\"color:#a6e22e\">control<\/span>.<span style=\"color:#a6e22e\">setValue<\/span>(<span style=\"color:#a6e22e\">control<\/span>.<span style=\"color:#a6e22e\">_pendingValue<\/span>, {<span style=\"color:#a6e22e\">emitModelToViewChange<\/span>: <span style=\"color:#66d9ef\">false<\/span>});\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#75715e\">\/\/ If you have something like `&lt;input [(ngModel)]=&#34;myValue&#34;&gt;`\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>  <span style=\"color:#75715e\">\/\/ this will allow `myValue` to be the new value that comes from the view\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>  <span style=\"color:#a6e22e\">dir<\/span>.<span style=\"color:#a6e22e\">viewToModelUpdate<\/span>(<span style=\"color:#a6e22e\">control<\/span>.<span style=\"color:#a6e22e\">_pendingValue<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">control<\/span>.<span style=\"color:#a6e22e\">_pendingChange<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">false<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ MODEL -&gt; VIEW\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span><span style=\"color:#66d9ef\">function<\/span> <span style=\"color:#a6e22e\">setUpModelChangePipeline<\/span>(<span style=\"color:#a6e22e\">control<\/span>: <span style=\"color:#66d9ef\">FormControl<\/span>, <span style=\"color:#a6e22e\">dir<\/span>: <span style=\"color:#66d9ef\">NgControl<\/span>)<span style=\"color:#f92672\">:<\/span> <span style=\"color:#66d9ef\">void<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">control<\/span>.<span style=\"color:#a6e22e\">registerOnChange<\/span>((<span style=\"color:#a6e22e\">newValue<\/span>: <span style=\"color:#66d9ef\">any<\/span>, <span style=\"color:#a6e22e\">emitModelEvent<\/span>: <span style=\"color:#66d9ef\">boolean<\/span>) <span style=\"color:#f92672\">=&gt;<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#75715e\">\/\/ control -&gt; view\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>    <span style=\"color:#a6e22e\">dir<\/span>.<span style=\"color:#a6e22e\">valueAccessor<\/span> <span style=\"color:#f92672\">!<\/span>.<span style=\"color:#a6e22e\">writeValue<\/span>(<span style=\"color:#a6e22e\">newValue<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#75715e\">\/\/ control -&gt; ngModel\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>    <span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#a6e22e\">emitModelEvent<\/span>) <span style=\"color:#a6e22e\">dir<\/span>.<span style=\"color:#a6e22e\">viewToModelUpdate<\/span>(<span style=\"color:#a6e22e\">newValue<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>  });\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p>Here is once again the <code>ControlValueAccessor<\/code> interface:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-tsx\" data-lang=\"tsx\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">export<\/span> <span style=\"color:#66d9ef\">interface<\/span> <span style=\"color:#a6e22e\">ControlValueAccessor<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">writeValue<\/span>(<span style=\"color:#a6e22e\">obj<\/span>: <span style=\"color:#66d9ef\">any<\/span>)<span style=\"color:#f92672\">:<\/span> <span style=\"color:#66d9ef\">void<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">registerOnChange<\/span>(<span style=\"color:#a6e22e\">fn<\/span>: <span style=\"color:#66d9ef\">any<\/span>)<span style=\"color:#f92672\">:<\/span> <span style=\"color:#66d9ef\">void<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">registerOnTouched<\/span>(<span style=\"color:#a6e22e\">fn<\/span>: <span style=\"color:#66d9ef\">any<\/span>)<span style=\"color:#f92672\">:<\/span> <span style=\"color:#66d9ef\">void<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">setDisabledState<\/span><span style=\"color:#f92672\">?<\/span>(<span style=\"color:#a6e22e\">isDisabled<\/span>: <span style=\"color:#66d9ef\">boolean<\/span>)<span style=\"color:#f92672\">:<\/span> <span style=\"color:#66d9ef\">void<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p>As you can see, the <code>setUpViewChangePipeline<\/code> method is how the <code>AbstractControlDirective<\/code>(the <code>dir<\/code> argument) connects the <strong>view<\/strong> with the <strong>model<\/strong>(unidirectional connection), by assigning a <strong>callback function<\/strong> to <code>ControlValueAccessor.onChange<\/code>. This will allow an action that happens in the view to be propagated into the model.<\/p>\n<p>Here&rsquo;s a concrete implementation of <code>ControlValueAccessor.registerOnChange<\/code>:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-tsx\" data-lang=\"tsx\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">@Directive<\/span>({\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">selector<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;input[custom-value-accessor][type=text][ngModel]&#39;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">host<\/span><span style=\"color:#f92672\">:<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#e6db74\">&#39;(input)&#39;<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;onChange($event.target.value)&#39;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  }\n<\/span><\/span><span style=\"display:flex;\"><span>})\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">export<\/span> <span style=\"color:#66d9ef\">class<\/span> <span style=\"color:#a6e22e\">CustomValueAccessor<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">registerOnChange<\/span>(<span style=\"color:#a6e22e\">fn<\/span><span style=\"color:#f92672\">:<\/span> (<span style=\"color:#a6e22e\">_<\/span>: <span style=\"color:#66d9ef\">any<\/span>) <span style=\"color:#f92672\">=&gt;<\/span> <span style=\"color:#66d9ef\">void<\/span>)<span style=\"color:#f92672\">:<\/span> <span style=\"color:#66d9ef\">void<\/span> { <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">onChange<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">fn<\/span>; }\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p>The <code>setUpModelChangePipeline<\/code> will allow the <code>AbstractControlDirective<\/code> to <strong>connect<\/strong> the <strong>model<\/strong> with the <strong>view<\/strong>. This means that every time <code>FormControl.setValue()<\/code> is invoked, <strong>all the callback functions registered<\/strong> within that <code>FormControl<\/code> will be invoked as well, in order to update that view based on the new model&rsquo;s value.<\/p>\n<p>Notice that I said <em>all the callback functions.<\/em> This is because multiple <code>AbstractControlDirective<\/code> can make use of the same <code>FormControl<\/code> instance.<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-tsx\" data-lang=\"tsx\"><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ Inside `FormControl`\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span><span style=\"color:#a6e22e\">_onChange<\/span>: <span style=\"color:#66d9ef\">Function<\/span>[] <span style=\"color:#f92672\">=<\/span> [];\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">registerOnChange<\/span>(<span style=\"color:#a6e22e\">fn<\/span>: <span style=\"color:#66d9ef\">Function<\/span>)<span style=\"color:#f92672\">:<\/span> <span style=\"color:#66d9ef\">void<\/span> { <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">_onChange<\/span>.<span style=\"color:#a6e22e\">push<\/span>(<span style=\"color:#a6e22e\">fn<\/span>); }\n<\/span><\/span><\/code><\/pre><\/div><div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-tsx\" data-lang=\"tsx\"><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ FormControl.setValue\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span><span style=\"color:#a6e22e\">setValue<\/span>(<span style=\"color:#a6e22e\">value<\/span>: <span style=\"color:#66d9ef\">any<\/span>, <span style=\"color:#a6e22e\">options<\/span><span style=\"color:#f92672\">:<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">onlySelf?<\/span>: <span style=\"color:#66d9ef\">boolean<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">emitEvent?<\/span>: <span style=\"color:#66d9ef\">boolean<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">emitModelToViewChange?<\/span>: <span style=\"color:#66d9ef\">boolean<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">emitViewToModelChange?<\/span>: <span style=\"color:#66d9ef\">boolean<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>} <span style=\"color:#f92672\">=<\/span> {})<span style=\"color:#f92672\">:<\/span> <span style=\"color:#66d9ef\">void<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>  (<span style=\"color:#66d9ef\">this<\/span> <span style=\"color:#66d9ef\">as<\/span>{<span style=\"color:#a6e22e\">value<\/span>: <span style=\"color:#66d9ef\">any<\/span>}).<span style=\"color:#a6e22e\">value<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">_pendingValue<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">value<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">_onChange<\/span>.<span style=\"color:#a6e22e\">length<\/span> <span style=\"color:#f92672\">&amp;&amp;<\/span> <span style=\"color:#a6e22e\">options<\/span>.<span style=\"color:#a6e22e\">emitModelToViewChange<\/span> <span style=\"color:#f92672\">!==<\/span> <span style=\"color:#66d9ef\">false<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">_onChange<\/span>.<span style=\"color:#a6e22e\">forEach<\/span>(\n<\/span><\/span><span style=\"display:flex;\"><span>        (<span style=\"color:#a6e22e\">changeFn<\/span>) <span style=\"color:#f92672\">=&gt;<\/span> <span style=\"color:#a6e22e\">changeFn<\/span>(<span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">value<\/span>, <span style=\"color:#a6e22e\">options<\/span>.<span style=\"color:#a6e22e\">emitViewToModelChange<\/span> <span style=\"color:#f92672\">!==<\/span> <span style=\"color:#66d9ef\">false<\/span>));\n<\/span><\/span><span style=\"display:flex;\"><span>  }\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">updateValueAndValidity<\/span>(<span style=\"color:#a6e22e\">options<\/span>); <span style=\"color:#75715e\">\/\/ Update ancestors\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>}\n<\/span><\/span><\/code><\/pre><\/div><p>Here&rsquo;s an example:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-html\" data-lang=\"html\"><span style=\"display:flex;\"><span>&lt;<span style=\"color:#f92672\">form<\/span>&gt;\n<\/span><\/span><span style=\"display:flex;\"><span>  &lt;<span style=\"color:#f92672\">input<\/span> <span style=\"color:#a6e22e\">type<\/span><span style=\"color:#f92672\">=<\/span><span style=\"color:#e6db74\">&#34;radio&#34;<\/span> <span style=\"color:#a6e22e\">ngModel<\/span> <span style=\"color:#a6e22e\">name<\/span><span style=\"color:#f92672\">=<\/span><span style=\"color:#e6db74\">&#34;genre&#34;<\/span> <span style=\"color:#a6e22e\">value<\/span><span style=\"color:#f92672\">=<\/span><span style=\"color:#e6db74\">&#34;horror&#34;<\/span>&gt;\n<\/span><\/span><span style=\"display:flex;\"><span>  &lt;<span style=\"color:#f92672\">input<\/span> <span style=\"color:#a6e22e\">type<\/span><span style=\"color:#f92672\">=<\/span><span style=\"color:#e6db74\">&#34;radio&#34;<\/span> <span style=\"color:#a6e22e\">ngModel<\/span> <span style=\"color:#a6e22e\">name<\/span><span style=\"color:#f92672\">=<\/span><span style=\"color:#e6db74\">&#34;genre&#34;<\/span> <span style=\"color:#a6e22e\">value<\/span><span style=\"color:#f92672\">=<\/span><span style=\"color:#e6db74\">&#34;comedy&#34;<\/span>&gt;\n<\/span><\/span><span style=\"display:flex;\"><span>&lt;\/<span style=\"color:#f92672\">form<\/span>&gt;\n<\/span><\/span><\/code><\/pre><\/div><p>The <code>setUpControl(control, dir)<\/code> will be called twice, once for every <code>ngModel<\/code>. But, on every call, the <code>control<\/code>(a <code>FormControl<\/code> instance) argument will be the same. This means that <code>control.onChanges<\/code> will contain 2 callback function, one for each <code>ControlValueAccessor<\/code>(<code>&lt;input type=&quot;radio&quot;&gt;<\/code> has the <code>RadioControlValueAccessor<\/code> bound to it).<\/p>\n<p>As a side note, the <code>ControlValueAccessor.registerOnTouched<\/code> follows the same principle as <code>ControlValueAccessor.registerOnChange<\/code>:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-tsx\" data-lang=\"tsx\"><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ Called inside `setUpControl`\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span><span style=\"color:#66d9ef\">function<\/span> <span style=\"color:#a6e22e\">setUpBlurPipeline<\/span>(<span style=\"color:#a6e22e\">control<\/span>: <span style=\"color:#66d9ef\">FormControl<\/span>, <span style=\"color:#a6e22e\">dir<\/span>: <span style=\"color:#66d9ef\">NgControl<\/span>)<span style=\"color:#f92672\">:<\/span> <span style=\"color:#66d9ef\">void<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">dir<\/span>.<span style=\"color:#a6e22e\">valueAccessor<\/span> <span style=\"color:#f92672\">!<\/span>.<span style=\"color:#a6e22e\">registerOnTouched<\/span>(() <span style=\"color:#f92672\">=&gt;<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">control<\/span>.<span style=\"color:#a6e22e\">_pendingTouched<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">true<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#a6e22e\">control<\/span>.<span style=\"color:#a6e22e\">updateOn<\/span> <span style=\"color:#f92672\">===<\/span> <span style=\"color:#e6db74\">&#39;blur&#39;<\/span> <span style=\"color:#f92672\">&amp;&amp;<\/span> <span style=\"color:#a6e22e\">control<\/span>.<span style=\"color:#a6e22e\">_pendingChange<\/span>) <span style=\"color:#a6e22e\">updateControl<\/span>(<span style=\"color:#a6e22e\">control<\/span>, <span style=\"color:#a6e22e\">dir<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#a6e22e\">control<\/span>.<span style=\"color:#a6e22e\">updateOn<\/span> <span style=\"color:#f92672\">!==<\/span> <span style=\"color:#e6db74\">&#39;submit&#39;<\/span>) <span style=\"color:#a6e22e\">control<\/span>.<span style=\"color:#a6e22e\">markAsTouched<\/span>();\n<\/span><\/span><span style=\"display:flex;\"><span>  });\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p>This will allow the <strong>model<\/strong> to be <strong>updated<\/strong> whenever the <strong>blur event occurs<\/strong> inside the view.<\/p>\n<h2 id=\"template-driven-forms-and-reactive-forms\">\n  <span>\n  Template Driven Forms and Reactive Forms\n  <\/span>\n  <a href=\"#template-driven-forms-and-reactive-forms\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><p>Both strategies are very powerful, but, in my opinion, Reactive Forms come handy when dealing with complex, dynamic logic.<\/p>\n<h3 id=\"template-driven-forms\">\n  <span>\n  Template Driven Forms\n  <\/span>\n  <a href=\"#template-driven-forms\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h3><p>When using this strategy, most of the logic that concerns the form&rsquo;s construction is performed inside the view. This means that the <code>AbstractControl<\/code> <strong>tree<\/strong> is being <strong>created<\/strong> <strong>while<\/strong> the <strong>view<\/strong> is <strong>being built<\/strong>.\nHere are the tools we can use when following this <strong>template-driven<\/strong> approach:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-tsx\" data-lang=\"tsx\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">export<\/span> <span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">TEMPLATE_DRIVEN_DIRECTIVES<\/span>: <span style=\"color:#66d9ef\">Type<\/span>&lt;<span style=\"color:#f92672\">any<\/span>&gt;[] <span style=\"color:#f92672\">=<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>    [<span style=\"color:#a6e22e\">NgModel<\/span>, <span style=\"color:#a6e22e\">NgModelGroup<\/span>, <span style=\"color:#a6e22e\">NgForm<\/span>];\n<\/span><\/span><\/code><\/pre><\/div><h3 id=\"ngmodel\">\n  <span>\n  NgModel\n  <\/span>\n  <a href=\"#ngmodel\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h3><p>It&rsquo;s a <strong>form-control-based<\/strong> directive, <strong>connects<\/strong> the <strong>view layer<\/strong> with the <strong>model layer<\/strong>(<code>FormControl<\/code>) and vice versa and. It also registers the <code>FormControl<\/code> into the <code>AbstractControl<\/code> tree.<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-tsx\" data-lang=\"tsx\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">@Input<\/span>(<span style=\"color:#e6db74\">&#39;ngModelOptions&#39;<\/span>)\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">options<\/span> <span style=\"color:#f92672\">!:<\/span> {<span style=\"color:#a6e22e\">name?<\/span>: <span style=\"color:#66d9ef\">string<\/span>, <span style=\"color:#a6e22e\">standalone?<\/span>: <span style=\"color:#66d9ef\">boolean<\/span>, <span style=\"color:#a6e22e\">updateOn<\/span><span style=\"color:#f92672\">?:<\/span> <span style=\"color:#e6db74\">&#39;change&#39;<\/span> <span style=\"color:#f92672\">|<\/span> <span style=\"color:#e6db74\">&#39;blur&#39;<\/span> <span style=\"color:#f92672\">|<\/span> <span style=\"color:#e6db74\">&#39;submit&#39;<\/span>};\n<\/span><\/span><\/code><\/pre><\/div><p>When using this directive, you can also specify some options:<\/p>\n<p>If you want to use a standalone FormControl instance, you can follow this approach:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-html\" data-lang=\"html\"><span style=\"display:flex;\"><span>&lt;<span style=\"color:#f92672\">form<\/span> <span style=\"color:#960050;background-color:#1e0010\">#<\/span><span style=\"color:#a6e22e\">f<\/span><span style=\"color:#f92672\">=<\/span><span style=\"color:#e6db74\">&#34;ngForm&#34;<\/span>&gt;\n<\/span><\/span><span style=\"display:flex;\"><span>  &lt;<span style=\"color:#f92672\">input<\/span> <span style=\"color:#960050;background-color:#1e0010\">[<\/span><span style=\"color:#a6e22e\">ngModelOptions<\/span><span style=\"color:#960050;background-color:#1e0010\">]=&#34;{<\/span> <span style=\"color:#a6e22e\">standalone:<\/span> <span style=\"color:#a6e22e\">true<\/span> <span style=\"color:#960050;background-color:#1e0010\">}&#34;<\/span> <span style=\"color:#960050;background-color:#1e0010\">#<\/span><span style=\"color:#a6e22e\">myNgModel<\/span><span style=\"color:#f92672\">=<\/span><span style=\"color:#e6db74\">&#34;ngModel&#34;<\/span> <span style=\"color:#a6e22e\">name<\/span><span style=\"color:#f92672\">=<\/span><span style=\"color:#e6db74\">&#34;name&#34;<\/span> <span style=\"color:#a6e22e\">ngModel<\/span> <span style=\"color:#a6e22e\">type<\/span><span style=\"color:#f92672\">=<\/span><span style=\"color:#e6db74\">&#34;text&#34;<\/span>&gt;\n<\/span><\/span><span style=\"display:flex;\"><span>&lt;\/<span style=\"color:#f92672\">form<\/span>&gt;\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>{{ myNgModel.value }}\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>&lt;<span style=\"color:#f92672\">br<\/span>&gt;\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>{{ f.value | json }}\n<\/span><\/span><\/code><\/pre><\/div><p><a href=\"https:\/\/ng-run.com\/edit\/Xx0irFLVo4FdueEBtSAF?open=app%2Fexample-standalone.component.ts\" target=\"_blank\" rel=\"noopener\"><em>ng-run Example.<\/em><\/a><\/p>\n<h3 id=\"ngmodelgroup\">\n  <span>\n  NgModelGroup\n  <\/span>\n  <a href=\"#ngmodelgroup\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h3><p>Provides a way to group multiple <code>NgModel<\/code> and <code>NgModelGroup<\/code> directives. In the model layer, this is represented by a <strong>non-top-level<\/strong> <code>FormGroup<\/code> instance. It also registers the <code>FormGroup<\/code> into the <code>AbstractControl<\/code> tree.<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-html\" data-lang=\"html\"><span style=\"display:flex;\"><span>&lt;<span style=\"color:#f92672\">form<\/span>&gt; <span style=\"color:#75715e\">&lt;!-- `NgForm` - automatically bound to `&lt;form&gt;` --&gt;<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>  &lt;<span style=\"color:#f92672\">input<\/span> <span style=\"color:#a6e22e\">type<\/span><span style=\"color:#f92672\">=<\/span><span style=\"color:#e6db74\">&#34;text&#34;<\/span> <span style=\"color:#a6e22e\">ngModel<\/span> <span style=\"color:#a6e22e\">name<\/span><span style=\"color:#f92672\">=<\/span><span style=\"color:#e6db74\">&#34;companyName&#34;<\/span>\/&gt;\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>  &lt;<span style=\"color:#f92672\">div<\/span> <span style=\"color:#a6e22e\">ngModelGroup<\/span><span style=\"color:#f92672\">=<\/span><span style=\"color:#e6db74\">&#34;personal&#34;<\/span>&gt;\n<\/span><\/span><span style=\"display:flex;\"><span>    &lt;<span style=\"color:#f92672\">input<\/span> <span style=\"color:#a6e22e\">type<\/span><span style=\"color:#f92672\">=<\/span><span style=\"color:#e6db74\">&#34;text&#34;<\/span> <span style=\"color:#a6e22e\">ngModel<\/span> <span style=\"color:#a6e22e\">name<\/span><span style=\"color:#f92672\">=<\/span><span style=\"color:#e6db74\">&#34;name&#34;<\/span>\/&gt;\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>    &lt;<span style=\"color:#f92672\">div<\/span> <span style=\"color:#a6e22e\">ngModelGroup<\/span><span style=\"color:#f92672\">=<\/span><span style=\"color:#e6db74\">&#34;address&#34;<\/span>&gt;\n<\/span><\/span><span style=\"display:flex;\"><span>      &lt;<span style=\"color:#f92672\">input<\/span> <span style=\"color:#a6e22e\">type<\/span><span style=\"color:#f92672\">=<\/span><span style=\"color:#e6db74\">&#34;text&#34;<\/span> <span style=\"color:#a6e22e\">ngModel<\/span> <span style=\"color:#a6e22e\">name<\/span><span style=\"color:#f92672\">=<\/span><span style=\"color:#e6db74\">&#34;city&#34;<\/span>\/&gt;\n<\/span><\/span><span style=\"display:flex;\"><span>      &lt;<span style=\"color:#f92672\">input<\/span> <span style=\"color:#a6e22e\">type<\/span><span style=\"color:#f92672\">=<\/span><span style=\"color:#e6db74\">&#34;text&#34;<\/span> <span style=\"color:#a6e22e\">ngModel<\/span> <span style=\"color:#a6e22e\">name<\/span><span style=\"color:#f92672\">=<\/span><span style=\"color:#e6db74\">&#34;street&#34;<\/span> \/&gt;\n<\/span><\/span><span style=\"display:flex;\"><span>    &lt;\/<span style=\"color:#f92672\">div<\/span>&gt;\n<\/span><\/span><span style=\"display:flex;\"><span>  &lt;\/<span style=\"color:#f92672\">div<\/span>&gt;\n<\/span><\/span><span style=\"display:flex;\"><span>&lt;\/<span style=\"color:#f92672\">form<\/span>&gt;\n<\/span><\/span><\/code><\/pre><\/div><p>The first occurrence of <code>NgModelGroup<\/code> must be a child of <code>NgForm<\/code>:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-html\" data-lang=\"html\"><span style=\"display:flex;\"><span><span style=\"color:#75715e\">&lt;!-- Valid --&gt;<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>&lt;<span style=\"color:#f92672\">form<\/span>&gt;\n<\/span><\/span><span style=\"display:flex;\"><span>  &lt;<span style=\"color:#f92672\">ng-container<\/span> <span style=\"color:#960050;background-color:#1e0010\">#<\/span><span style=\"color:#a6e22e\">myGrp<\/span><span style=\"color:#f92672\">=<\/span><span style=\"color:#e6db74\">&#34;ngModelGroup&#34;<\/span> <span style=\"color:#a6e22e\">ngModelGroup<\/span><span style=\"color:#f92672\">=<\/span><span style=\"color:#e6db74\">&#34;address&#34;<\/span>&gt;\n<\/span><\/span><span style=\"display:flex;\"><span>    &lt;<span style=\"color:#f92672\">input<\/span> <span style=\"color:#a6e22e\">type<\/span><span style=\"color:#f92672\">=<\/span><span style=\"color:#e6db74\">&#34;text&#34;<\/span><span style=\"color:#a6e22e\">ngModel<\/span> <span style=\"color:#a6e22e\">name<\/span><span style=\"color:#f92672\">=<\/span><span style=\"color:#e6db74\">&#34;city&#34;<\/span> \/&gt;\n<\/span><\/span><span style=\"display:flex;\"><span>    &lt;<span style=\"color:#f92672\">input<\/span> <span style=\"color:#a6e22e\">type<\/span><span style=\"color:#f92672\">=<\/span><span style=\"color:#e6db74\">&#34;text&#34;<\/span> <span style=\"color:#a6e22e\">ngModel<\/span> <span style=\"color:#a6e22e\">name<\/span><span style=\"color:#f92672\">=<\/span><span style=\"color:#e6db74\">&#34;street&#34;<\/span>&gt;\n<\/span><\/span><span style=\"display:flex;\"><span>  &lt;\/<span style=\"color:#f92672\">ng-container<\/span>&gt;\n<\/span><\/span><span style=\"display:flex;\"><span>&lt;\/<span style=\"color:#f92672\">form<\/span>&gt;\n<\/span><\/span><\/code><\/pre><\/div><div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-html\" data-lang=\"html\"><span style=\"display:flex;\"><span><span style=\"color:#75715e\">&lt;!-- Invalid: `No provider for ControlContainer ...` --&gt;<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>&lt;<span style=\"color:#f92672\">div<\/span> <span style=\"color:#960050;background-color:#1e0010\">#<\/span><span style=\"color:#a6e22e\">myGrp<\/span><span style=\"color:#f92672\">=<\/span><span style=\"color:#e6db74\">&#34;ngModelGroup&#34;<\/span> <span style=\"color:#a6e22e\">ngModelGroup<\/span><span style=\"color:#f92672\">=<\/span><span style=\"color:#e6db74\">&#34;address&#34;<\/span>&gt;\n<\/span><\/span><span style=\"display:flex;\"><span>  &lt;<span style=\"color:#f92672\">input<\/span> <span style=\"color:#a6e22e\">type<\/span><span style=\"color:#f92672\">=<\/span><span style=\"color:#e6db74\">&#34;text&#34;<\/span><span style=\"color:#a6e22e\">ngModel<\/span> <span style=\"color:#a6e22e\">name<\/span><span style=\"color:#f92672\">=<\/span><span style=\"color:#e6db74\">&#34;city&#34;<\/span> \/&gt;\n<\/span><\/span><span style=\"display:flex;\"><span>  &lt;<span style=\"color:#f92672\">input<\/span> <span style=\"color:#a6e22e\">type<\/span><span style=\"color:#f92672\">=<\/span><span style=\"color:#e6db74\">&#34;text&#34;<\/span> <span style=\"color:#a6e22e\">ngModel<\/span> <span style=\"color:#a6e22e\">name<\/span><span style=\"color:#f92672\">=<\/span><span style=\"color:#e6db74\">&#34;street&#34;<\/span>&gt;\n<\/span><\/span><span style=\"display:flex;\"><span>&lt;\/<span style=\"color:#f92672\">div<\/span>&gt;\n<\/span><\/span><\/code><\/pre><\/div><h3 id=\"ngform\">\n  <span>\n  NgForm\n  <\/span>\n  <a href=\"#ngform\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h3><p>It groups multiple <code>NgModel<\/code> and <code>NgModelGroup<\/code> directives. In the model layer, it is represented by a <strong>top-level<\/strong> instance, so it listens to form-specific events, such as <code>reset<\/code> and <code>submit<\/code>. Also, it is automatically bound to <code>&lt;form&gt;<\/code> blog_tags.<\/p>\n<p>In the model, this is the root <code>FormGroup<\/code> instance of the <code>AbstractControl<\/code> tree.<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-html\" data-lang=\"html\"><span style=\"display:flex;\"><span>&lt;<span style=\"color:#f92672\">form<\/span>&gt; <span style=\"color:#75715e\">&lt;!-- NgForm --&gt;<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>  &lt;<span style=\"color:#f92672\">input<\/span> <span style=\"color:#a6e22e\">ngModel<\/span> <span style=\"color:#a6e22e\">name<\/span><span style=\"color:#f92672\">=<\/span><span style=\"color:#e6db74\">&#34;companyName&#34;<\/span> <span style=\"color:#a6e22e\">type<\/span><span style=\"color:#f92672\">=<\/span><span style=\"color:#e6db74\">&#34;text&#34;<\/span>&gt; <span style=\"color:#75715e\">&lt;!-- NgModel --&gt;<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>  &lt;<span style=\"color:#f92672\">div<\/span> <span style=\"color:#a6e22e\">ngModelGroup<\/span><span style=\"color:#f92672\">=<\/span><span style=\"color:#e6db74\">&#34;address&#34;<\/span>&gt; <span style=\"color:#75715e\">&lt;!-- NgModelGroup --&gt;<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>    &lt;<span style=\"color:#f92672\">input<\/span> <span style=\"color:#a6e22e\">ngModel<\/span> <span style=\"color:#a6e22e\">name<\/span><span style=\"color:#f92672\">=<\/span><span style=\"color:#e6db74\">&#34;city&#34;<\/span> <span style=\"color:#a6e22e\">type<\/span><span style=\"color:#f92672\">=<\/span><span style=\"color:#e6db74\">&#34;text&#34;<\/span>&gt; <span style=\"color:#75715e\">&lt;!-- NgModel --&gt;<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>    &lt;<span style=\"color:#f92672\">input<\/span> <span style=\"color:#a6e22e\">ngModel<\/span> <span style=\"color:#a6e22e\">name<\/span><span style=\"color:#f92672\">=<\/span><span style=\"color:#e6db74\">&#34;street&#34;<\/span> <span style=\"color:#a6e22e\">type<\/span><span style=\"color:#f92672\">=<\/span><span style=\"color:#e6db74\">&#34;text&#34;<\/span>&gt; <span style=\"color:#75715e\">&lt;!-- NgModel --&gt;<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>  &lt;\/<span style=\"color:#f92672\">div<\/span>&gt;\n<\/span><\/span><span style=\"display:flex;\"><span>&lt;\/<span style=\"color:#f92672\">form<\/span>&gt;\n<\/span><\/span><\/code><\/pre><\/div><h3 id=\"reactive-forms\">\n  <span>\n  Reactive Forms\n  <\/span>\n  <a href=\"#reactive-forms\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h3><p>As opposed to <em>Template Driven Forms<\/em>, when using <em>Reactive Forms<\/em> the <strong>form<\/strong> is <strong>already created<\/strong> when the <strong>view is being built<\/strong>.<\/p>\n<p>Here are the tools we can use when following this reactive approach:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-tsx\" data-lang=\"tsx\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">export<\/span> <span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">REACTIVE_DRIVEN_DIRECTIVES<\/span>: <span style=\"color:#66d9ef\">Type<\/span>&lt;<span style=\"color:#f92672\">any<\/span>&gt;[] <span style=\"color:#f92672\">=<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>    [<span style=\"color:#a6e22e\">FormControlDirective<\/span>, <span style=\"color:#a6e22e\">FormGroupDirective<\/span>, <span style=\"color:#a6e22e\">FormControlName<\/span>, <span style=\"color:#a6e22e\">FormGroupName<\/span>, <span style=\"color:#a6e22e\">FormArrayName<\/span>];\n<\/span><\/span><\/code><\/pre><\/div><h3 id=\"formcontroldirective\">\n  <span>\n  FormControlDirective\n  <\/span>\n  <a href=\"#formcontroldirective\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h3><p>It is a <strong>form-control-based directive<\/strong>, it is the bridge between the 2 main layers: <strong>view<\/strong> and <strong>model<\/strong>.<\/p>\n<p>It receives a <code>FormControl<\/code> instance(<code>[formControl]=&quot;formControlInstance&quot;<\/code>) which is already synced with, because <code>formControlInstance<\/code> is already part of an existing <code>AbstractControl<\/code> tree. Therefore, the important thing to do here is just to bind the <code>formControlInstance<\/code> to the current <strong>DOM element<\/strong> by using the <strong>value accessor<\/strong>.<\/p>\n<p>If you want to use a standalone <code>FormControl<\/code> instance, you can follow this approach:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-tsx\" data-lang=\"tsx\"><span style=\"display:flex;\"><span>&lt;<span style=\"color:#f92672\">input<\/span> <span style=\"color:#960050;background-color:#1e0010\">#<\/span><span style=\"color:#a6e22e\">f<\/span><span style=\"color:#f92672\">=<\/span><span style=\"color:#e6db74\">&#34;ngForm&#34;<\/span> <span style=\"color:#960050;background-color:#1e0010\">[<\/span><span style=\"color:#a6e22e\">formControl<\/span><span style=\"color:#960050;background-color:#1e0010\">]=&#34;<\/span><span style=\"color:#a6e22e\">formControlInstance<\/span><span style=\"color:#960050;background-color:#1e0010\">&#34;<\/span> <span style=\"color:#a6e22e\">type<\/span><span style=\"color:#f92672\">=<\/span><span style=\"color:#e6db74\">&#34;text&#34;<\/span>&gt;\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>{{ <span style=\"color:#a6e22e\">f<\/span>.<span style=\"color:#a6e22e\">value<\/span> }}\n<\/span><\/span><\/code><\/pre><\/div><h3 id=\"formgroupdirective\">\n  <span>\n  FormGroupDirective\n  <\/span>\n  <a href=\"#formgroupdirective\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h3><p>In the model layer, it is a top-level <code>FormGroup<\/code> instance(<code>&lt;form [formGroup]=&quot;formGroupInstance&quot;&gt;<\/code>). This also means that it listens to form-specific events, such as reset and submit. <code>formGroupInstance<\/code> is the root of an <strong>already built<\/strong> <code>AbstractControl<\/code> tree.<\/p>\n<h3 id=\"formcontrolname\">\n  <span>\n  FormControlName\n  <\/span>\n  <a href=\"#formcontrolname\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h3><p>It receives a string as argument(<code>[formControlName]=&quot;nameOfFormControlInstance&quot;<\/code>) and its task is to determine the <code>FormControl<\/code> instance depending on the provided control name(<code>nameOfFormControlInstance<\/code>) and the position in the view. If the <code>FormControl<\/code> instance is not found based on the path, an error will be thrown.<\/p>\n<p>Thus, <code>nameOfFormControlInstance<\/code> must be a valid name, because it relies on the <strong>form container<\/strong> to correctly add this <code>FormControl<\/code> to the <code>AbstractControl<\/code> tree.<\/p>\n<p>As mentioned before, the path is inferred based on the position of the **DOM element(**or custom component) and <code>nameOfFormControlInstance<\/code>:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-tsx\" data-lang=\"tsx\"><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ control - is, in this case, the top level `FormGroup` instance\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span><span style=\"color:#66d9ef\">function<\/span> <span style=\"color:#a6e22e\">_find<\/span>(<span style=\"color:#a6e22e\">control<\/span>: <span style=\"color:#66d9ef\">AbstractControl<\/span>, <span style=\"color:#a6e22e\">path<\/span>: <span style=\"color:#66d9ef\">Array<\/span>&lt;<span style=\"color:#f92672\">string<\/span><span style=\"color:#960050;background-color:#1e0010\">|<\/span><span style=\"color:#a6e22e\">number<\/span>&gt;<span style=\"color:#f92672\">|<\/span> <span style=\"color:#66d9ef\">string<\/span>, <span style=\"color:#a6e22e\">delimiter<\/span>: <span style=\"color:#66d9ef\">string<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#a6e22e\">path<\/span> <span style=\"color:#f92672\">==<\/span> <span style=\"color:#66d9ef\">null<\/span>) <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#66d9ef\">null<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#f92672\">!<\/span>(<span style=\"color:#a6e22e\">path<\/span> <span style=\"color:#66d9ef\">instanceof<\/span> Array)) {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">path<\/span> <span style=\"color:#f92672\">=<\/span> (&lt;<span style=\"color:#f92672\">string<\/span>&gt;<span style=\"color:#a6e22e\">path<\/span>).<span style=\"color:#a6e22e\">split<\/span>(<span style=\"color:#a6e22e\">delimiter<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>  }\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#a6e22e\">path<\/span> <span style=\"color:#66d9ef\">instanceof<\/span> Array <span style=\"color:#f92672\">&amp;&amp;<\/span> (<span style=\"color:#a6e22e\">path<\/span>.<span style=\"color:#a6e22e\">length<\/span> <span style=\"color:#f92672\">===<\/span> <span style=\"color:#ae81ff\">0<\/span>)) <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#66d9ef\">null<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">return<\/span> (&lt;<span style=\"color:#f92672\">Array<\/span><span style=\"color:#960050;background-color:#1e0010\">&lt;<\/span><span style=\"color:#a6e22e\">string<\/span><span style=\"color:#960050;background-color:#1e0010\">|<\/span><span style=\"color:#a6e22e\">number<\/span>&gt;<span style=\"color:#f92672\">&gt;<\/span><span style=\"color:#a6e22e\">path<\/span>).<span style=\"color:#a6e22e\">reduce<\/span>((<span style=\"color:#a6e22e\">v<\/span>: <span style=\"color:#66d9ef\">AbstractControl<\/span> <span style=\"color:#f92672\">|<\/span> <span style=\"color:#66d9ef\">null<\/span>, <span style=\"color:#a6e22e\">name<\/span>) <span style=\"color:#f92672\">=&gt;<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#a6e22e\">v<\/span> <span style=\"color:#66d9ef\">instanceof<\/span> <span style=\"color:#a6e22e\">FormGroup<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#a6e22e\">v<\/span>.<span style=\"color:#a6e22e\">controls<\/span>.<span style=\"color:#a6e22e\">hasOwnProperty<\/span>(<span style=\"color:#a6e22e\">name<\/span> <span style=\"color:#66d9ef\">as<\/span> <span style=\"color:#66d9ef\">string<\/span>) <span style=\"color:#f92672\">?<\/span> <span style=\"color:#a6e22e\">v<\/span>.<span style=\"color:#a6e22e\">controls<\/span>[<span style=\"color:#a6e22e\">name<\/span>] <span style=\"color:#f92672\">:<\/span> <span style=\"color:#66d9ef\">null<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>    }\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#a6e22e\">v<\/span> <span style=\"color:#66d9ef\">instanceof<\/span> <span style=\"color:#a6e22e\">FormArray<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#a6e22e\">v<\/span>.<span style=\"color:#a6e22e\">at<\/span>(&lt;<span style=\"color:#f92672\">number<\/span>&gt;<span style=\"color:#a6e22e\">name<\/span>) <span style=\"color:#f92672\">||<\/span> <span style=\"color:#66d9ef\">null<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>    }\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#66d9ef\">null<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>  }, <span style=\"color:#a6e22e\">control<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-html\" data-lang=\"html\"><span style=\"display:flex;\"><span>&lt;<span style=\"color:#f92672\">form<\/span> <span style=\"color:#960050;background-color:#1e0010\">[<\/span><span style=\"color:#a6e22e\">formGroup<\/span><span style=\"color:#960050;background-color:#1e0010\">]=&#34;<\/span><span style=\"color:#a6e22e\">myFormGroup<\/span><span style=\"color:#960050;background-color:#1e0010\">&#34;<\/span>&gt;\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#75715e\">&lt;!-- path: &#39;name&#39; --&gt;<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>  &lt;<span style=\"color:#f92672\">input<\/span> <span style=\"color:#a6e22e\">formControlName<\/span><span style=\"color:#f92672\">=<\/span><span style=\"color:#e6db74\">&#34;name&#34;<\/span> <span style=\"color:#a6e22e\">type<\/span><span style=\"color:#f92672\">=<\/span><span style=\"color:#e6db74\">&#34;text&#34;<\/span>&gt;\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#75715e\">&lt;!-- path: &#39;address&#39; --&gt;<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>  &lt;<span style=\"color:#f92672\">ng-container<\/span> <span style=\"color:#a6e22e\">formGroupName<\/span><span style=\"color:#f92672\">=<\/span><span style=\"color:#e6db74\">&#34;address&#34;<\/span>&gt;\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#75715e\">&lt;!-- path: [&#39;address&#39;, &#39;city&#39;] --&gt;<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>    &lt;<span style=\"color:#f92672\">input<\/span> <span style=\"color:#a6e22e\">formControlName<\/span><span style=\"color:#f92672\">=<\/span><span style=\"color:#e6db74\">&#34;city&#34;<\/span> <span style=\"color:#a6e22e\">type<\/span><span style=\"color:#f92672\">=<\/span><span style=\"color:#e6db74\">&#34;text&#34;<\/span>&gt;\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#75715e\">&lt;!-- path: [&#39;address&#39;, &#39;street&#39;] --&gt;<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>    &lt;<span style=\"color:#f92672\">input<\/span> <span style=\"color:#a6e22e\">formControlName<\/span><span style=\"color:#f92672\">=<\/span><span style=\"color:#e6db74\">&#34;street&#34;<\/span> <span style=\"color:#a6e22e\">type<\/span><span style=\"color:#f92672\">=<\/span><span style=\"color:#e6db74\">&#34;text&#34;<\/span>&gt;\n<\/span><\/span><span style=\"display:flex;\"><span>  &lt;\/<span style=\"color:#f92672\">ng-container<\/span>&gt;\n<\/span><\/span><span style=\"display:flex;\"><span>&lt;\/<span style=\"color:#f92672\">form<\/span>&gt;\n<\/span><\/span><\/code><\/pre><\/div><p>And this is how the path of each directive is determined:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-tsx\" data-lang=\"tsx\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">export<\/span> <span style=\"color:#66d9ef\">function<\/span> <span style=\"color:#a6e22e\">controlPath<\/span>(<span style=\"color:#a6e22e\">name<\/span>: <span style=\"color:#66d9ef\">string<\/span>, <span style=\"color:#a6e22e\">parent<\/span>: <span style=\"color:#66d9ef\">ControlContainer<\/span>)<span style=\"color:#f92672\">:<\/span> <span style=\"color:#66d9ef\">string<\/span>[] {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">return<\/span> [...<span style=\"color:#a6e22e\">parent<\/span>.<span style=\"color:#a6e22e\">path<\/span> <span style=\"color:#f92672\">!<\/span>, <span style=\"color:#a6e22e\">name<\/span>];\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p>It is worth mentioning that <code>nameOfFormControlInstance<\/code> can&rsquo;t be dynamic. Once the <code>FormControl<\/code> is added, it <strong>can&rsquo;t<\/strong> be <strong>changed<\/strong> <strong>automatically<\/strong>.(<a href=\"https:\/\/ng-run.com\/edit\/o2piqt1V5jzCxhSj2HJB\" target=\"_blank\" rel=\"noopener\"><em>Example<\/em><\/a>)<\/p>\n<p>Here&rsquo;s why:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-tsx\" data-lang=\"tsx\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">@Directive<\/span>({<span style=\"color:#a6e22e\">selector<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;[formControlName]&#39;<\/span>, <span style=\"color:#a6e22e\">providers<\/span><span style=\"color:#f92672\">:<\/span> [<span style=\"color:#a6e22e\">controlNameBinding<\/span>]})\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">export<\/span> <span style=\"color:#66d9ef\">class<\/span> <span style=\"color:#a6e22e\">FormControlName<\/span> <span style=\"color:#66d9ef\">extends<\/span> <span style=\"color:#a6e22e\">NgControl<\/span> <span style=\"color:#66d9ef\">implements<\/span> <span style=\"color:#a6e22e\">OnChanges<\/span>, <span style=\"color:#a6e22e\">OnDestroy<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#75715e\">\/* ... *\/<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">ngOnChanges<\/span>(<span style=\"color:#a6e22e\">changes<\/span>: <span style=\"color:#66d9ef\">SimpleChanges<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#f92672\">!<\/span><span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">_added<\/span>) <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">_setUpControl<\/span>();\n<\/span><\/span><span style=\"display:flex;\"><span>  }\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">private<\/span> <span style=\"color:#a6e22e\">_setUpControl() {<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">_checkParentType<\/span>();\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#75715e\">\/\/ formDirective - points to the top-level `FormGroup` instance\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>    (<span style=\"color:#66d9ef\">this<\/span> <span style=\"color:#66d9ef\">as<\/span>{<span style=\"color:#a6e22e\">control<\/span>: <span style=\"color:#66d9ef\">FormControl<\/span>}).<span style=\"color:#a6e22e\">control<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">formDirective<\/span>.<span style=\"color:#a6e22e\">addControl<\/span>(<span style=\"color:#66d9ef\">this<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">control<\/span>.<span style=\"color:#a6e22e\">disabled<\/span> <span style=\"color:#f92672\">&amp;&amp;<\/span> <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">valueAccessor<\/span> <span style=\"color:#f92672\">!<\/span>.<span style=\"color:#a6e22e\">setDisabledState<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">valueAccessor<\/span> <span style=\"color:#f92672\">!<\/span>.<span style=\"color:#a6e22e\">setDisabledState<\/span> <span style=\"color:#f92672\">!<\/span>(<span style=\"color:#66d9ef\">true<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>    }\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">_added<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">true<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>  }\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#75715e\">\/* ... *\/<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p>However, if you still want to change the <code>FormControl<\/code> instance when the <code>nameOfFormControlInstance<\/code> changes, you can use this:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-tsx\" data-lang=\"tsx\"><span style=\"display:flex;\"><span>{<span style=\"color:#a6e22e\">FormArray<\/span><span style=\"color:#f92672\">|<\/span><span style=\"color:#a6e22e\">FormGroup<\/span>}.<span style=\"color:#a6e22e\">setControl<\/span>(<span style=\"color:#a6e22e\">ctrlName<\/span>, <span style=\"color:#a6e22e\">formControlInstance<\/span>)\n<\/span><\/span><\/code><\/pre><\/div><h3 id=\"formgroupname\">\n  <span>\n  FormGroupName\n  <\/span>\n  <a href=\"#formgroupname\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h3><p>It receives a string as an argument(<code>[formGroupName]=&quot;nameOfFormGroupInstance&quot;<\/code>) and based on that argument, it has to find the right <code>FormGroup<\/code> instance.<\/p>\n<p>It can&rsquo;t be used as a top-level form control container, it must be registered within an exiting <code>FormGroupDirective<\/code>.<\/p>\n<p>Suppose you have a form like this:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-tsx\" data-lang=\"tsx\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">address<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">fb<\/span>.<span style=\"color:#a6e22e\">group<\/span>({\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">street<\/span>: <span style=\"color:#66d9ef\">this.fb.control<\/span>(<span style=\"color:#e6db74\">&#39;&#39;<\/span>),\n<\/span><\/span><span style=\"display:flex;\"><span>});\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">form<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">fb<\/span>.<span style=\"color:#a6e22e\">group<\/span>({\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">name<\/span>: <span style=\"color:#66d9ef\">this.fb.control<\/span>(<span style=\"color:#e6db74\">&#39;&#39;<\/span>),\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">address<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>});\n<\/span><\/span><\/code><\/pre><\/div><p>Writing this in the view will result in an error(<em>Cannot find control with name: &lsquo;street&rsquo;<\/em>):<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-html\" data-lang=\"html\"><span style=\"display:flex;\"><span>&lt;<span style=\"color:#f92672\">form<\/span> <span style=\"color:#960050;background-color:#1e0010\">#<\/span><span style=\"color:#a6e22e\">f<\/span><span style=\"color:#f92672\">=<\/span><span style=\"color:#e6db74\">&#34;ngForm&#34;<\/span> <span style=\"color:#960050;background-color:#1e0010\">[<\/span><span style=\"color:#a6e22e\">formGroup<\/span><span style=\"color:#960050;background-color:#1e0010\">]=&#34;<\/span><span style=\"color:#a6e22e\">form<\/span><span style=\"color:#960050;background-color:#1e0010\">&#34;<\/span>&gt;\n<\/span><\/span><span style=\"display:flex;\"><span>  &lt;<span style=\"color:#f92672\">input<\/span> <span style=\"color:#a6e22e\">formControlName<\/span><span style=\"color:#f92672\">=<\/span><span style=\"color:#e6db74\">&#34;name&#34;<\/span> <span style=\"color:#a6e22e\">type<\/span><span style=\"color:#f92672\">=<\/span><span style=\"color:#e6db74\">&#34;text&#34;<\/span>&gt;\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>  &lt;<span style=\"color:#f92672\">input<\/span> <span style=\"color:#a6e22e\">formControlName<\/span><span style=\"color:#f92672\">=<\/span><span style=\"color:#e6db74\">&#34;street&#34;<\/span> <span style=\"color:#a6e22e\">type<\/span><span style=\"color:#f92672\">=<\/span><span style=\"color:#e6db74\">&#34;text&#34;<\/span>&gt;\n<\/span><\/span><span style=\"display:flex;\"><span>&lt;\/<span style=\"color:#f92672\">form<\/span>&gt;\n<\/span><\/span><\/code><\/pre><\/div><p>The way to solve this is to use the <code>FormGroupName<\/code> directive in order to create a <strong>sub-group<\/strong>, so that the view will correlate with model.<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-html\" data-lang=\"html\"><span style=\"display:flex;\"><span>&lt;<span style=\"color:#f92672\">form<\/span> <span style=\"color:#960050;background-color:#1e0010\">#<\/span><span style=\"color:#a6e22e\">f<\/span><span style=\"color:#f92672\">=<\/span><span style=\"color:#e6db74\">&#34;ngForm&#34;<\/span> <span style=\"color:#960050;background-color:#1e0010\">[<\/span><span style=\"color:#a6e22e\">formGroup<\/span><span style=\"color:#960050;background-color:#1e0010\">]=&#34;<\/span><span style=\"color:#a6e22e\">form<\/span><span style=\"color:#960050;background-color:#1e0010\">&#34;<\/span>&gt;\n<\/span><\/span><span style=\"display:flex;\"><span>  &lt;<span style=\"color:#f92672\">input<\/span> <span style=\"color:#a6e22e\">formControlName<\/span><span style=\"color:#f92672\">=<\/span><span style=\"color:#e6db74\">&#34;name&#34;<\/span> <span style=\"color:#a6e22e\">type<\/span><span style=\"color:#f92672\">=<\/span><span style=\"color:#e6db74\">&#34;text&#34;<\/span>&gt;\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>  &lt;<span style=\"color:#f92672\">ng-container<\/span> <span style=\"color:#a6e22e\">formGroupName<\/span><span style=\"color:#f92672\">=<\/span><span style=\"color:#e6db74\">&#34;address&#34;<\/span>&gt;\n<\/span><\/span><span style=\"display:flex;\"><span>    &lt;<span style=\"color:#f92672\">input<\/span> <span style=\"color:#a6e22e\">formControlName<\/span><span style=\"color:#f92672\">=<\/span><span style=\"color:#e6db74\">&#34;street&#34;<\/span> <span style=\"color:#a6e22e\">type<\/span><span style=\"color:#f92672\">=<\/span><span style=\"color:#e6db74\">&#34;text&#34;<\/span>&gt;\n<\/span><\/span><span style=\"display:flex;\"><span>  &lt;\/<span style=\"color:#f92672\">ng-container<\/span>&gt;\n<\/span><\/span><span style=\"display:flex;\"><span>&lt;\/<span style=\"color:#f92672\">form<\/span>&gt;\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>{{ f.value | json }}\n<\/span><\/span><\/code><\/pre><\/div><blockquote>\n<p>When using <code>FormControlDirective<\/code>(<code>[formControl]=&quot;formControlInstance&quot;<\/code>), this is not needed, because the <code>FormControlDirective<\/code> does not have to find the <code>FormControl<\/code> instance since it already receives one through <code>formControlInstance<\/code>.<\/p>\n<\/blockquote>\n<h3 id=\"formarrayname\">\n  <span>\n  FormArrayName\n  <\/span>\n  <a href=\"#formarrayname\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h3><p>Same as <code>FormGroupName<\/code>, except that is has to find an existing <code>FormArray<\/code> instance in the <code>AbstractControl<\/code> tree.<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-tsx\" data-lang=\"tsx\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">fooForm<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">fb<\/span>.<span style=\"color:#a6e22e\">group<\/span>({\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">movies<\/span>: <span style=\"color:#66d9ef\">this.fb.array<\/span>([\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">fb<\/span>.<span style=\"color:#a6e22e\">control<\/span>(<span style=\"color:#e6db74\">&#39;action&#39;<\/span>),\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">fb<\/span>.<span style=\"color:#a6e22e\">control<\/span>(<span style=\"color:#e6db74\">&#39;horror&#39;<\/span>),\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">fb<\/span>.<span style=\"color:#a6e22e\">control<\/span>(<span style=\"color:#e6db74\">&#39;mistery&#39;<\/span>),\n<\/span><\/span><span style=\"display:flex;\"><span>  ]),\n<\/span><\/span><span style=\"display:flex;\"><span>});\n<\/span><\/span><\/code><\/pre><\/div><div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-html\" data-lang=\"html\"><span style=\"display:flex;\"><span>&lt;<span style=\"color:#f92672\">form<\/span> <span style=\"color:#960050;background-color:#1e0010\">#<\/span><span style=\"color:#a6e22e\">f<\/span><span style=\"color:#f92672\">=<\/span><span style=\"color:#e6db74\">&#34;ngForm&#34;<\/span> <span style=\"color:#960050;background-color:#1e0010\">[<\/span><span style=\"color:#a6e22e\">formGroup<\/span><span style=\"color:#960050;background-color:#1e0010\">]=&#34;<\/span><span style=\"color:#a6e22e\">fooForm<\/span><span style=\"color:#960050;background-color:#1e0010\">&#34;<\/span>&gt;\n<\/span><\/span><span style=\"display:flex;\"><span>  &lt;<span style=\"color:#f92672\">ng-container<\/span> <span style=\"color:#a6e22e\">formArrayName<\/span><span style=\"color:#f92672\">=<\/span><span style=\"color:#e6db74\">&#34;movies&#34;<\/span>&gt;\n<\/span><\/span><span style=\"display:flex;\"><span>    &lt;<span style=\"color:#f92672\">input<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#960050;background-color:#1e0010\">*<\/span><span style=\"color:#a6e22e\">ngFor<\/span><span style=\"color:#f92672\">=<\/span><span style=\"color:#e6db74\">&#34;let _ of fooForm.controls[&#39;movies&#39;].controls; let idx = index;&#34;<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#960050;background-color:#1e0010\">[<\/span><span style=\"color:#a6e22e\">formControlName<\/span><span style=\"color:#960050;background-color:#1e0010\">]=&#34;<\/span><span style=\"color:#a6e22e\">idx<\/span><span style=\"color:#960050;background-color:#1e0010\">&#34;<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#a6e22e\">type<\/span><span style=\"color:#f92672\">=<\/span><span style=\"color:#e6db74\">&#34;text&#34;<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>    &gt;\n<\/span><\/span><span style=\"display:flex;\"><span>  &lt;\/<span style=\"color:#f92672\">ng-container<\/span>&gt;\n<\/span><\/span><span style=\"display:flex;\"><span>&lt;\/<span style=\"color:#f92672\">form<\/span>&gt;\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>{{ f.value | json }}\n<\/span><\/span><\/code><\/pre><\/div><h2 id=\"validators\">\n  <span>\n  Validators\n  <\/span>\n  <a href=\"#validators\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><p>Validators allow developers to put constraints on <code>AbstractControl<\/code> instances(<code>FormControl<\/code>, <code>FormArray<\/code>, <code>FormGroup<\/code>).<\/p>\n<p>Validators are <strong>set and run<\/strong> when the <code>AbstractControl<\/code> tree is initialized. If you want to set them after the initialization has taken place, you can use <code>AbstractFormControl.setValidators<\/code> and <code>AbstractFormControl.setAsyncValidators<\/code> to set them and <code>AbstractFormControl.updateValueAndValidity<\/code> to run them.<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-tsx\" data-lang=\"tsx\"><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">setValidators<\/span>(<span style=\"color:#a6e22e\">newValidator<\/span>: <span style=\"color:#66d9ef\">ValidatorFn<\/span><span style=\"color:#f92672\">|<\/span><span style=\"color:#a6e22e\">ValidatorFn<\/span>[]<span style=\"color:#f92672\">|<\/span><span style=\"color:#66d9ef\">null<\/span>)<span style=\"color:#f92672\">:<\/span> <span style=\"color:#66d9ef\">void<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">validator<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">coerceToValidator<\/span>(<span style=\"color:#a6e22e\">newValidator<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">updateValueAndValidity<\/span>(<span style=\"color:#a6e22e\">opts<\/span><span style=\"color:#f92672\">:<\/span> {<span style=\"color:#a6e22e\">onlySelf?<\/span>: <span style=\"color:#66d9ef\">boolean<\/span>, <span style=\"color:#a6e22e\">emitEvent?<\/span>: <span style=\"color:#66d9ef\">boolean<\/span>} <span style=\"color:#f92672\">=<\/span> {})<span style=\"color:#f92672\">:<\/span> <span style=\"color:#66d9ef\">void<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#75715e\">\/* ... *\/<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">enabled<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">_cancelExistingSubscription<\/span>();\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#75715e\">\/\/ Run sync validators\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>    <span style=\"color:#75715e\">\/\/ and will invoke `this.validator`\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>    (<span style=\"color:#66d9ef\">this<\/span> <span style=\"color:#66d9ef\">as<\/span>{<span style=\"color:#a6e22e\">errors<\/span>: <span style=\"color:#66d9ef\">ValidationErrors<\/span> <span style=\"color:#f92672\">|<\/span> <span style=\"color:#66d9ef\">null<\/span>}).<span style=\"color:#a6e22e\">errors<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">_runValidator<\/span>();\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#75715e\">\/\/ If `errors` property is not null -&gt; status = &#39;INVALID&#39;\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>    (<span style=\"color:#66d9ef\">this<\/span> <span style=\"color:#66d9ef\">as<\/span>{<span style=\"color:#a6e22e\">status<\/span>: <span style=\"color:#66d9ef\">string<\/span>}).<span style=\"color:#a6e22e\">status<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">_calculateStatus<\/span>();\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">status<\/span> <span style=\"color:#f92672\">===<\/span> <span style=\"color:#a6e22e\">VALID<\/span> <span style=\"color:#f92672\">||<\/span> <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">status<\/span> <span style=\"color:#f92672\">===<\/span> <span style=\"color:#a6e22e\">PENDING<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">_runAsyncValidator<\/span>(<span style=\"color:#a6e22e\">opts<\/span>.<span style=\"color:#a6e22e\">emitEvent<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>    }\n<\/span><\/span><span style=\"display:flex;\"><span>  }\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#75715e\">\/* ... *\/<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">_parent<\/span> <span style=\"color:#f92672\">&amp;&amp;<\/span> <span style=\"color:#f92672\">!<\/span><span style=\"color:#a6e22e\">opts<\/span>.<span style=\"color:#a6e22e\">onlySelf<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">_parent<\/span>.<span style=\"color:#a6e22e\">updateValueAndValidity<\/span>(<span style=\"color:#a6e22e\">opts<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>  }\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p>From the above code snippet we can also deduce that <strong>async validators<\/strong> will not run if the <strong>sync validators<\/strong> returned <strong>errors<\/strong>.<\/p>\n<h3 id=\"usage-of-built-in-validators\">\n  <span>\n  Usage of built-in Validators\n  <\/span>\n  <a href=\"#usage-of-built-in-validators\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h3><p>The built-in validators are available as <strong>directives<\/strong> or as <strong>static members<\/strong> of the <code>Validator<\/code> class.<\/p>\n<p>For example, the <strong>email validator<\/strong> can be used directly in the view like this:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-html\" data-lang=\"html\"><span style=\"display:flex;\"><span>&lt;<span style=\"color:#f92672\">form<\/span>&gt;\n<\/span><\/span><span style=\"display:flex;\"><span>  &lt;<span style=\"color:#f92672\">input<\/span> <span style=\"color:#a6e22e\">email<\/span> <span style=\"color:#a6e22e\">ngModel<\/span> <span style=\"color:#a6e22e\">name<\/span><span style=\"color:#f92672\">=<\/span><span style=\"color:#e6db74\">&#34;email&#34;<\/span> <span style=\"color:#a6e22e\">type<\/span><span style=\"color:#f92672\">=<\/span><span style=\"color:#e6db74\">&#34;text&#34;<\/span>&gt;\n<\/span><\/span><span style=\"display:flex;\"><span>&lt;\/<span style=\"color:#f92672\">form<\/span>&gt;\n<\/span><\/span><\/code><\/pre><\/div><div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-tsx\" data-lang=\"tsx\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">@Directive<\/span>({\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">selector<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;[email][formControlName],[email][formControl],[email][ngModel]&#39;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">providers<\/span><span style=\"color:#f92672\">:<\/span> [<span style=\"color:#a6e22e\">EMAIL_VALIDATOR<\/span>]\n<\/span><\/span><span style=\"display:flex;\"><span>})\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">export<\/span> <span style=\"color:#66d9ef\">class<\/span> <span style=\"color:#a6e22e\">EmailValidator<\/span> <span style=\"color:#66d9ef\">implements<\/span> <span style=\"color:#a6e22e\">Validator<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#75715e\">\/* ... *\/<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">validate<\/span>(<span style=\"color:#a6e22e\">control<\/span>: <span style=\"color:#66d9ef\">AbstractControl<\/span>)<span style=\"color:#f92672\">:<\/span> <span style=\"color:#a6e22e\">ValidationErrors<\/span><span style=\"color:#f92672\">|<\/span><span style=\"color:#66d9ef\">null<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">_enabled<\/span> <span style=\"color:#f92672\">?<\/span> <span style=\"color:#a6e22e\">Validators<\/span>.<span style=\"color:#a6e22e\">email<\/span>(<span style=\"color:#a6e22e\">control<\/span>) <span style=\"color:#f92672\">:<\/span> <span style=\"color:#66d9ef\">null<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>  }\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#75715e\">\/* ... *\/<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p>Whereas with <em>Reactive Forms<\/em> you&rsquo;d use it like this:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-tsx\" data-lang=\"tsx\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">form<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">new<\/span> <span style=\"color:#a6e22e\">FormGroup<\/span>({\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">name<\/span>: <span style=\"color:#66d9ef\">new<\/span> <span style=\"color:#a6e22e\">FormControl<\/span>(<span style=\"color:#a6e22e\">defaultValue<\/span>, [<span style=\"color:#a6e22e\">Validators<\/span>.<span style=\"color:#a6e22e\">Email<\/span>])\n<\/span><\/span><span style=\"display:flex;\"><span>})\n<\/span><\/span><\/code><\/pre><\/div><p>Although when using <em>Reactive Forms<\/em> the validators are usually set in the component class, you can still provide validators inside the view; when the <code>AbstractControl<\/code> instance is created, the validators will eventually be merged inside <code>setUpControl<\/code><\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-tsx\" data-lang=\"tsx\"><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ dir.validator - sync validators provided via directives(eg: `&lt;input email type=&#34;text&#34;&gt;`)\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ control.validator - sync validators provided through `Reactive Forms`(eg: new FormControl(&#39;&#39;, [syncValidators]))\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span><span style=\"color:#66d9ef\">export<\/span> <span style=\"color:#66d9ef\">function<\/span> <span style=\"color:#a6e22e\">setUpControl<\/span>(<span style=\"color:#a6e22e\">control<\/span>: <span style=\"color:#66d9ef\">FormControl<\/span>, <span style=\"color:#a6e22e\">dir<\/span>: <span style=\"color:#66d9ef\">NgControl<\/span>)<span style=\"color:#f92672\">:<\/span> <span style=\"color:#66d9ef\">void<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#f92672\">!<\/span><span style=\"color:#a6e22e\">control<\/span>) <span style=\"color:#a6e22e\">_throwError<\/span>(<span style=\"color:#a6e22e\">dir<\/span>, <span style=\"color:#e6db74\">&#39;Cannot find control with&#39;<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#f92672\">!<\/span><span style=\"color:#a6e22e\">dir<\/span>.<span style=\"color:#a6e22e\">valueAccessor<\/span>) <span style=\"color:#a6e22e\">_throwError<\/span>(<span style=\"color:#a6e22e\">dir<\/span>, <span style=\"color:#e6db74\">&#39;No value accessor for form control with&#39;<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">control<\/span>.<span style=\"color:#a6e22e\">validator<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">Validators<\/span>.<span style=\"color:#a6e22e\">compose<\/span>([<span style=\"color:#a6e22e\">control<\/span>.<span style=\"color:#a6e22e\">validator<\/span> <span style=\"color:#f92672\">!<\/span>, <span style=\"color:#a6e22e\">dir<\/span>.<span style=\"color:#a6e22e\">validator<\/span>]);\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">control<\/span>.<span style=\"color:#a6e22e\">asyncValidator<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">Validators<\/span>.<span style=\"color:#a6e22e\">composeAsync<\/span>([<span style=\"color:#a6e22e\">control<\/span>.<span style=\"color:#a6e22e\">asyncValidator<\/span> <span style=\"color:#f92672\">!<\/span>, <span style=\"color:#a6e22e\">dir<\/span>.<span style=\"color:#a6e22e\">asyncValidator<\/span>]);\n<\/span><\/span><span style=\"display:flex;\"><span>  \n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#75715e\">\/* ... *\/<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><h3 id=\"validators-composition\">\n  <span>\n  Validators&rsquo; Composition\n  <\/span>\n  <a href=\"#validators-composition\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h3><p>Validators can be provided from multiple sources: either form the view, or from the class, or from both.<\/p>\n<p>All the validators will be eventually be <strong>merged into a single function<\/strong> that, when invoked, will execute all of them sequentially and accumulate their results(returned errors).<\/p>\n<p>Those which implement the <code>Validator<\/code> interface will be normalized first, meaning that will be transformed into a function that, when invoked, will execute the <code>Validator.validate<\/code> method:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-tsx\" data-lang=\"tsx\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">export<\/span> <span style=\"color:#66d9ef\">function<\/span> <span style=\"color:#a6e22e\">normalizeValidator<\/span>(<span style=\"color:#a6e22e\">validator<\/span>: <span style=\"color:#66d9ef\">ValidatorFn<\/span> <span style=\"color:#f92672\">|<\/span> <span style=\"color:#a6e22e\">Validator<\/span>)<span style=\"color:#f92672\">:<\/span> <span style=\"color:#a6e22e\">ValidatorFn<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">if<\/span> ((&lt;<span style=\"color:#f92672\">Validator<\/span>&gt;<span style=\"color:#a6e22e\">validator<\/span>).<span style=\"color:#a6e22e\">validate<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">return<\/span> (<span style=\"color:#a6e22e\">c<\/span>: <span style=\"color:#66d9ef\">AbstractControl<\/span>) <span style=\"color:#f92672\">=&gt;<\/span> (&lt;<span style=\"color:#f92672\">Validator<\/span>&gt;<span style=\"color:#a6e22e\">validator<\/span>).<span style=\"color:#a6e22e\">validate<\/span>(<span style=\"color:#a6e22e\">c<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>  } <span style=\"color:#66d9ef\">else<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">return<\/span> &lt;<span style=\"color:#f92672\">ValidatorFn<\/span>&gt;<span style=\"color:#a6e22e\">validator<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>  }\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p>Validators are set and merged(if needed) inside <code>setUpControl<\/code> function:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-tsx\" data-lang=\"tsx\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">export<\/span> <span style=\"color:#66d9ef\">function<\/span> <span style=\"color:#a6e22e\">setUpControl<\/span>(<span style=\"color:#a6e22e\">control<\/span>: <span style=\"color:#66d9ef\">FormControl<\/span>, <span style=\"color:#a6e22e\">dir<\/span>: <span style=\"color:#66d9ef\">NgControl<\/span>)<span style=\"color:#f92672\">:<\/span> <span style=\"color:#66d9ef\">void<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#f92672\">!<\/span><span style=\"color:#a6e22e\">control<\/span>) <span style=\"color:#a6e22e\">_throwError<\/span>(<span style=\"color:#a6e22e\">dir<\/span>, <span style=\"color:#e6db74\">&#39;Cannot find control with&#39;<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#f92672\">!<\/span><span style=\"color:#a6e22e\">dir<\/span>.<span style=\"color:#a6e22e\">valueAccessor<\/span>) <span style=\"color:#a6e22e\">_throwError<\/span>(<span style=\"color:#a6e22e\">dir<\/span>, <span style=\"color:#e6db74\">&#39;No value accessor for form control with&#39;<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">control<\/span>.<span style=\"color:#a6e22e\">validator<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">Validators<\/span>.<span style=\"color:#a6e22e\">compose<\/span>([<span style=\"color:#a6e22e\">control<\/span>.<span style=\"color:#a6e22e\">validator<\/span> <span style=\"color:#f92672\">!<\/span>, <span style=\"color:#a6e22e\">dir<\/span>.<span style=\"color:#a6e22e\">validator<\/span>]);\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">control<\/span>.<span style=\"color:#a6e22e\">asyncValidator<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">Validators<\/span>.<span style=\"color:#a6e22e\">composeAsync<\/span>([<span style=\"color:#a6e22e\">control<\/span>.<span style=\"color:#a6e22e\">asyncValidator<\/span> <span style=\"color:#f92672\">!<\/span>, <span style=\"color:#a6e22e\">dir<\/span>.<span style=\"color:#a6e22e\">asyncValidator<\/span>]);\n<\/span><\/span><span style=\"display:flex;\"><span>  \n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#75715e\">\/* ... *\/<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p>Let&rsquo;s explore the magic behind <code>Validators.compose<\/code>:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-tsx\" data-lang=\"tsx\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">export<\/span> <span style=\"color:#66d9ef\">class<\/span> <span style=\"color:#a6e22e\">Validators<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">static<\/span> <span style=\"color:#a6e22e\">compose<\/span>(<span style=\"color:#a6e22e\">validators<\/span><span style=\"color:#f92672\">:<\/span> (<span style=\"color:#a6e22e\">ValidatorFn<\/span><span style=\"color:#f92672\">|<\/span><span style=\"color:#66d9ef\">null<\/span><span style=\"color:#f92672\">|<\/span><span style=\"color:#66d9ef\">undefined<\/span>)[]<span style=\"color:#f92672\">|<\/span><span style=\"color:#66d9ef\">null<\/span>)<span style=\"color:#f92672\">:<\/span> <span style=\"color:#a6e22e\">ValidatorFn<\/span><span style=\"color:#f92672\">|<\/span><span style=\"color:#66d9ef\">null<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#f92672\">!<\/span><span style=\"color:#a6e22e\">validators<\/span>) <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#66d9ef\">null<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">presentValidators<\/span>: <span style=\"color:#66d9ef\">ValidatorFn<\/span>[] <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">validators<\/span>.<span style=\"color:#a6e22e\">filter<\/span>(<span style=\"color:#a6e22e\">isPresent<\/span>) <span style=\"color:#66d9ef\">as<\/span> <span style=\"color:#66d9ef\">any<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#a6e22e\">presentValidators<\/span>.<span style=\"color:#a6e22e\">length<\/span> <span style=\"color:#f92672\">==<\/span> <span style=\"color:#ae81ff\">0<\/span>) <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#66d9ef\">null<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#66d9ef\">function<\/span>(<span style=\"color:#a6e22e\">control<\/span>: <span style=\"color:#66d9ef\">AbstractControl<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#a6e22e\">_mergeErrors<\/span>(<span style=\"color:#a6e22e\">_executeValidators<\/span>(<span style=\"color:#a6e22e\">control<\/span>, <span style=\"color:#a6e22e\">presentValidators<\/span>));\n<\/span><\/span><span style=\"display:flex;\"><span>    };\n<\/span><\/span><span style=\"display:flex;\"><span>  }\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">function<\/span> <span style=\"color:#a6e22e\">_executeValidators<\/span>(<span style=\"color:#a6e22e\">control<\/span>: <span style=\"color:#66d9ef\">AbstractControl<\/span>, <span style=\"color:#a6e22e\">validators<\/span>: <span style=\"color:#66d9ef\">ValidatorFn<\/span>[])<span style=\"color:#f92672\">:<\/span> <span style=\"color:#66d9ef\">any<\/span>[] {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#a6e22e\">validators<\/span>.<span style=\"color:#a6e22e\">map<\/span>(<span style=\"color:#a6e22e\">v<\/span> <span style=\"color:#f92672\">=&gt;<\/span> <span style=\"color:#a6e22e\">v<\/span>(<span style=\"color:#a6e22e\">control<\/span>));\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ Accumulate errors\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span><span style=\"color:#66d9ef\">function<\/span> <span style=\"color:#a6e22e\">_mergeErrors<\/span>(<span style=\"color:#a6e22e\">arrayOfErrors<\/span>: <span style=\"color:#66d9ef\">ValidationErrors<\/span>[])<span style=\"color:#f92672\">:<\/span> <span style=\"color:#a6e22e\">ValidationErrors<\/span><span style=\"color:#f92672\">|<\/span><span style=\"color:#66d9ef\">null<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">res<\/span><span style=\"color:#f92672\">:<\/span> {[<span style=\"color:#a6e22e\">key<\/span>: <span style=\"color:#66d9ef\">string<\/span>]<span style=\"color:#f92672\">:<\/span> <span style=\"color:#66d9ef\">any<\/span>} <span style=\"color:#f92672\">=<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#a6e22e\">arrayOfErrors<\/span>.<span style=\"color:#a6e22e\">reduce<\/span>((<span style=\"color:#a6e22e\">res<\/span>: <span style=\"color:#66d9ef\">ValidationErrors<\/span> <span style=\"color:#f92672\">|<\/span> <span style=\"color:#66d9ef\">null<\/span>, <span style=\"color:#a6e22e\">errors<\/span>: <span style=\"color:#66d9ef\">ValidationErrors<\/span> <span style=\"color:#f92672\">|<\/span> <span style=\"color:#66d9ef\">null<\/span>) <span style=\"color:#f92672\">=&gt;<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#a6e22e\">errors<\/span> <span style=\"color:#f92672\">!=<\/span> <span style=\"color:#66d9ef\">null<\/span> <span style=\"color:#f92672\">?<\/span> {...<span style=\"color:#a6e22e\">res<\/span> <span style=\"color:#f92672\">!<\/span>, ...<span style=\"color:#a6e22e\">errors<\/span>} <span style=\"color:#f92672\">:<\/span> <span style=\"color:#a6e22e\">res<\/span> <span style=\"color:#f92672\">!<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>      }, {});\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">return<\/span> Object.<span style=\"color:#a6e22e\">keys<\/span>(<span style=\"color:#a6e22e\">res<\/span>).<span style=\"color:#a6e22e\">length<\/span> <span style=\"color:#f92672\">===<\/span> <span style=\"color:#ae81ff\">0<\/span> <span style=\"color:#f92672\">?<\/span> <span style=\"color:#66d9ef\">null<\/span> <span style=\"color:#f92672\">:<\/span> <span style=\"color:#a6e22e\">res<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p>The same logic applies to <code>Validator.composeAsync<\/code>, with the exception of the way validators are executed. First, it will convert all the async validators into observables and then will execute them with the help of the <code>forkJoin<\/code> operator.<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-tsx\" data-lang=\"tsx\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">export<\/span> <span style=\"color:#66d9ef\">class<\/span> <span style=\"color:#a6e22e\">Validators<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">static<\/span> <span style=\"color:#a6e22e\">composeAsync<\/span>(<span style=\"color:#a6e22e\">validators<\/span><span style=\"color:#f92672\">:<\/span> (<span style=\"color:#a6e22e\">AsyncValidatorFn<\/span><span style=\"color:#f92672\">|<\/span><span style=\"color:#66d9ef\">null<\/span>)[])<span style=\"color:#f92672\">:<\/span> <span style=\"color:#a6e22e\">AsyncValidatorFn<\/span><span style=\"color:#f92672\">|<\/span><span style=\"color:#66d9ef\">null<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#f92672\">!<\/span><span style=\"color:#a6e22e\">validators<\/span>) <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#66d9ef\">null<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">presentValidators<\/span>: <span style=\"color:#66d9ef\">AsyncValidatorFn<\/span>[] <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">validators<\/span>.<span style=\"color:#a6e22e\">filter<\/span>(<span style=\"color:#a6e22e\">isPresent<\/span>) <span style=\"color:#66d9ef\">as<\/span> <span style=\"color:#66d9ef\">any<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#a6e22e\">presentValidators<\/span>.<span style=\"color:#a6e22e\">length<\/span> <span style=\"color:#f92672\">==<\/span> <span style=\"color:#ae81ff\">0<\/span>) <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#66d9ef\">null<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#66d9ef\">function<\/span>(<span style=\"color:#a6e22e\">control<\/span>: <span style=\"color:#66d9ef\">AbstractControl<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">observables<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">_executeAsyncValidators<\/span>(<span style=\"color:#a6e22e\">control<\/span>, <span style=\"color:#a6e22e\">presentValidators<\/span>).<span style=\"color:#a6e22e\">map<\/span>(<span style=\"color:#a6e22e\">toObservable<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#a6e22e\">forkJoin<\/span>(<span style=\"color:#a6e22e\">observables<\/span>).<span style=\"color:#a6e22e\">pipe<\/span>(<span style=\"color:#a6e22e\">map<\/span>(<span style=\"color:#a6e22e\">_mergeErrors<\/span>));\n<\/span><\/span><span style=\"display:flex;\"><span>    };\n<\/span><\/span><span style=\"display:flex;\"><span>  }\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><h3 id=\"custom-validators\">\n  <span>\n  Custom Validators\n  <\/span>\n  <a href=\"#custom-validators\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h3><p>A recommended way to create a custom validator is to use it as a directive that implements the <code>Validator<\/code> interface:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-tsx\" data-lang=\"tsx\"><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ min-max-validator.directive.ts\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span><span style=\"color:#66d9ef\">@Directive<\/span>({\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">selector<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;[min-max-validator]&#39;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">providers<\/span><span style=\"color:#f92672\">:<\/span> [\n<\/span><\/span><span style=\"display:flex;\"><span>    {\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#a6e22e\">provide<\/span>: <span style=\"color:#66d9ef\">NG_VALIDATORS<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#a6e22e\">useExisting<\/span>: <span style=\"color:#66d9ef\">forwardRef<\/span>(() <span style=\"color:#f92672\">=&gt;<\/span> <span style=\"color:#a6e22e\">MinMaxValidator<\/span>),\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#a6e22e\">multi<\/span>: <span style=\"color:#66d9ef\">true<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>    }\n<\/span><\/span><span style=\"display:flex;\"><span>  ]\n<\/span><\/span><span style=\"display:flex;\"><span>})\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">export<\/span> <span style=\"color:#66d9ef\">class<\/span> <span style=\"color:#a6e22e\">MinMaxValidator<\/span> <span style=\"color:#66d9ef\">implements<\/span> <span style=\"color:#a6e22e\">Validator<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">constructor<\/span>() { }\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">validate<\/span> (<span style=\"color:#a6e22e\">f<\/span>: <span style=\"color:#66d9ef\">FormGroup<\/span>)<span style=\"color:#f92672\">:<\/span> <span style=\"color:#a6e22e\">ValidationErrors<\/span> <span style=\"color:#f92672\">|<\/span> <span style=\"color:#66d9ef\">null<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#a6e22e\">f<\/span>.<span style=\"color:#a6e22e\">pristine<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#66d9ef\">null<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>    }\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">const<\/span> { <span style=\"color:#a6e22e\">min<\/span>, <span style=\"color:#a6e22e\">max<\/span> } <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">f<\/span>.<span style=\"color:#a6e22e\">controls<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#75715e\">\/\/ `min` or `max` is not a number or is empty\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>    <span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#a6e22e\">min<\/span>.<span style=\"color:#a6e22e\">invalid<\/span> <span style=\"color:#f92672\">||<\/span> <span style=\"color:#a6e22e\">max<\/span>.<span style=\"color:#a6e22e\">invalid<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#66d9ef\">null<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>    }\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#f92672\">+<\/span><span style=\"color:#a6e22e\">min<\/span>.<span style=\"color:#a6e22e\">value<\/span> <span style=\"color:#f92672\">&gt;=<\/span> <span style=\"color:#f92672\">+<\/span><span style=\"color:#a6e22e\">max<\/span>.<span style=\"color:#a6e22e\">value<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#66d9ef\">return<\/span> { <span style=\"color:#a6e22e\">minGreaterMax<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;min cannot be greater than max!&#39;<\/span> };\n<\/span><\/span><span style=\"display:flex;\"><span>    }\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#66d9ef\">null<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>  }\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-html\" data-lang=\"html\"><span style=\"display:flex;\"><span>&lt;<span style=\"color:#f92672\">form<\/span> <span style=\"color:#960050;background-color:#1e0010\">#<\/span><span style=\"color:#a6e22e\">f<\/span><span style=\"color:#f92672\">=<\/span><span style=\"color:#e6db74\">&#34;ngForm&#34;<\/span>&gt;\n<\/span><\/span><span style=\"display:flex;\"><span>  &lt;<span style=\"color:#f92672\">ng-container<\/span> <span style=\"color:#a6e22e\">min-max-validator<\/span> <span style=\"color:#a6e22e\">ngModelGroup<\/span><span style=\"color:#f92672\">=<\/span><span style=\"color:#e6db74\">&#34;price&#34;<\/span> <span style=\"color:#960050;background-color:#1e0010\">#<\/span><span style=\"color:#a6e22e\">priceGrp<\/span><span style=\"color:#f92672\">=<\/span><span style=\"color:#e6db74\">&#34;ngModelGroup&#34;<\/span>&gt;\n<\/span><\/span><span style=\"display:flex;\"><span>    &lt;<span style=\"color:#f92672\">input<\/span> <span style=\"color:#a6e22e\">type<\/span><span style=\"color:#f92672\">=<\/span><span style=\"color:#e6db74\">&#34;text&#34;<\/span> <span style=\"color:#a6e22e\">ngModel<\/span> <span style=\"color:#a6e22e\">name<\/span><span style=\"color:#f92672\">=<\/span><span style=\"color:#e6db74\">&#34;min&#34;<\/span> <span style=\"color:#a6e22e\">pattern<\/span><span style=\"color:#f92672\">=<\/span><span style=\"color:#e6db74\">&#34;^\\d+$&#34;<\/span> <span style=\"color:#a6e22e\">required<\/span> \/&gt;\n<\/span><\/span><span style=\"display:flex;\"><span>    &lt;<span style=\"color:#f92672\">input<\/span> <span style=\"color:#a6e22e\">type<\/span><span style=\"color:#f92672\">=<\/span><span style=\"color:#e6db74\">&#34;text&#34;<\/span> <span style=\"color:#a6e22e\">ngModel<\/span> <span style=\"color:#a6e22e\">name<\/span><span style=\"color:#f92672\">=<\/span><span style=\"color:#e6db74\">&#34;max&#34;<\/span> <span style=\"color:#a6e22e\">pattern<\/span><span style=\"color:#f92672\">=<\/span><span style=\"color:#e6db74\">&#34;^\\d+$&#34;<\/span> <span style=\"color:#a6e22e\">required<\/span> &gt;\n<\/span><\/span><span style=\"display:flex;\"><span>  &lt;\/<span style=\"color:#f92672\">ng-container<\/span>&gt;\n<\/span><\/span><span style=\"display:flex;\"><span>&lt;\/<span style=\"color:#f92672\">form<\/span>&gt;\n<\/span><\/span><\/code><\/pre><\/div><p><a href=\"https:\/\/ng-run.com\/edit\/Xx0irFLVo4FdueEBtSAF?open=app%2Fmin-max-example.component.ts\" target=\"_blank\" rel=\"noopener\"><em>ng-run Example<\/em><\/a><\/p>\n<h3 id=\"dynamic-validators\">\n  <span>\n  Dynamic Validators\n  <\/span>\n  <a href=\"#dynamic-validators\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h3><p>The <code>Validator<\/code> interface looks like this:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-tsx\" data-lang=\"tsx\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">export<\/span> <span style=\"color:#66d9ef\">interface<\/span> <span style=\"color:#a6e22e\">Validator<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">validate<\/span>(<span style=\"color:#a6e22e\">control<\/span>: <span style=\"color:#66d9ef\">AbstractControl<\/span>)<span style=\"color:#f92672\">:<\/span> <span style=\"color:#a6e22e\">ValidationErrors<\/span><span style=\"color:#f92672\">|<\/span><span style=\"color:#66d9ef\">null<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">registerOnValidatorChange<\/span><span style=\"color:#f92672\">?<\/span>(<span style=\"color:#a6e22e\">fn<\/span><span style=\"color:#f92672\">:<\/span> () <span style=\"color:#f92672\">=&gt;<\/span> <span style=\"color:#66d9ef\">void<\/span>)<span style=\"color:#f92672\">:<\/span> <span style=\"color:#66d9ef\">void<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p>We can use the <code>registerOnValidatorChange<\/code> to register a <strong>callback function<\/strong> that should be called whenever the validator&rsquo;s inputs change. Invoking that callback function will ensure that your <code>AbstractControl<\/code> instance is in line with the updated validator.<\/p>\n<p>Example: <code>&lt;input [required]=&quot;true&quot;&gt;<\/code> &ndash;&gt; <code>&lt;input [required]=&quot;false&quot;&gt;<\/code><\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-tsx\" data-lang=\"tsx\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">@Directive<\/span>({\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">selector<\/span><span style=\"color:#f92672\">:<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#e6db74\">&#39;:not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]&#39;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">providers<\/span><span style=\"color:#f92672\">:<\/span> [<span style=\"color:#a6e22e\">REQUIRED_VALIDATOR<\/span>],\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">host<\/span><span style=\"color:#f92672\">:<\/span> {<span style=\"color:#e6db74\">&#39;[attr.required]&#39;<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;required ? &#34;&#34; : null&#39;<\/span>}\n<\/span><\/span><span style=\"display:flex;\"><span>})\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">export<\/span> <span style=\"color:#66d9ef\">class<\/span> <span style=\"color:#a6e22e\">RequiredValidator<\/span> <span style=\"color:#66d9ef\">implements<\/span> <span style=\"color:#a6e22e\">Validator<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">set<\/span> <span style=\"color:#a6e22e\">required<\/span>(<span style=\"color:#a6e22e\">value<\/span>: <span style=\"color:#66d9ef\">boolean<\/span><span style=\"color:#f92672\">|<\/span><span style=\"color:#66d9ef\">string<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">_required<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">value<\/span> <span style=\"color:#f92672\">!=<\/span> <span style=\"color:#66d9ef\">null<\/span> <span style=\"color:#f92672\">&amp;&amp;<\/span> <span style=\"color:#a6e22e\">value<\/span> <span style=\"color:#f92672\">!==<\/span> <span style=\"color:#66d9ef\">false<\/span> <span style=\"color:#f92672\">&amp;&amp;<\/span> <span style=\"color:#e6db74\">`<\/span><span style=\"color:#e6db74\">${<\/span><span style=\"color:#a6e22e\">value<\/span><span style=\"color:#e6db74\">}<\/span><span style=\"color:#e6db74\">`<\/span> <span style=\"color:#f92672\">!==<\/span> <span style=\"color:#e6db74\">&#39;false&#39;<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">_onChange<\/span>) <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">_onChange<\/span>();\n<\/span><\/span><span style=\"display:flex;\"><span>  }\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">registerOnValidatorChange<\/span>(<span style=\"color:#a6e22e\">fn<\/span><span style=\"color:#f92672\">:<\/span> () <span style=\"color:#f92672\">=&gt;<\/span> <span style=\"color:#66d9ef\">void<\/span>)<span style=\"color:#f92672\">:<\/span> <span style=\"color:#66d9ef\">void<\/span> { <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">_onChange<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">fn<\/span>; }\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-tsx\" data-lang=\"tsx\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">export<\/span> <span style=\"color:#66d9ef\">function<\/span> <span style=\"color:#a6e22e\">setUpControl<\/span>(<span style=\"color:#a6e22e\">control<\/span>: <span style=\"color:#66d9ef\">FormControl<\/span>, <span style=\"color:#a6e22e\">dir<\/span>: <span style=\"color:#66d9ef\">NgControl<\/span>)<span style=\"color:#f92672\">:<\/span> <span style=\"color:#66d9ef\">void<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#75715e\">\/* ... *\/<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>  \n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#75715e\">\/\/ re-run validation when validator binding changes, e.g. minlength=3 -&gt; minlength=4\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>  <span style=\"color:#a6e22e\">dir<\/span>.<span style=\"color:#a6e22e\">_rawValidators<\/span>.<span style=\"color:#a6e22e\">forEach<\/span>((<span style=\"color:#a6e22e\">validator<\/span>: <span style=\"color:#66d9ef\">Validator<\/span> <span style=\"color:#f92672\">|<\/span> <span style=\"color:#a6e22e\">ValidatorFn<\/span>) <span style=\"color:#f92672\">=&gt;<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">if<\/span> ((&lt;<span style=\"color:#f92672\">Validator<\/span>&gt;<span style=\"color:#a6e22e\">validator<\/span>).<span style=\"color:#a6e22e\">registerOnValidatorChange<\/span>)\n<\/span><\/span><span style=\"display:flex;\"><span>      (&lt;<span style=\"color:#f92672\">Validator<\/span>&gt;<span style=\"color:#a6e22e\">validator<\/span>).<span style=\"color:#a6e22e\">registerOnValidatorChange<\/span> <span style=\"color:#f92672\">!<\/span>(() <span style=\"color:#f92672\">=&gt;<\/span> <span style=\"color:#a6e22e\">control<\/span>.<span style=\"color:#a6e22e\">updateValueAndValidity<\/span>());\n<\/span><\/span><span style=\"display:flex;\"><span>  });\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">dir<\/span>.<span style=\"color:#a6e22e\">_rawAsyncValidators<\/span>.<span style=\"color:#a6e22e\">forEach<\/span>((<span style=\"color:#a6e22e\">validator<\/span>: <span style=\"color:#66d9ef\">AsyncValidator<\/span> <span style=\"color:#f92672\">|<\/span> <span style=\"color:#a6e22e\">AsyncValidatorFn<\/span>) <span style=\"color:#f92672\">=&gt;<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">if<\/span> ((&lt;<span style=\"color:#f92672\">Validator<\/span>&gt;<span style=\"color:#a6e22e\">validator<\/span>).<span style=\"color:#a6e22e\">registerOnValidatorChange<\/span>)\n<\/span><\/span><span style=\"display:flex;\"><span>      (&lt;<span style=\"color:#f92672\">Validator<\/span>&gt;<span style=\"color:#a6e22e\">validator<\/span>).<span style=\"color:#a6e22e\">registerOnValidatorChange<\/span> <span style=\"color:#f92672\">!<\/span>(() <span style=\"color:#f92672\">=&gt;<\/span> <span style=\"color:#a6e22e\">control<\/span>.<span style=\"color:#a6e22e\">updateValueAndValidity<\/span>());\n<\/span><\/span><span style=\"display:flex;\"><span>  });\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#75715e\">\/* ... *\/<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p><a href=\"https:\/\/ng-run.com\/edit\/Xx0irFLVo4FdueEBtSAF?open=app%2Fdynamic-validator.component.ts\" target=\"_blank\" rel=\"noopener\"><em>ng-run Example.<\/em><\/a><\/p>\n<h2 id=\"exploring-built-in-controlvalueaccessors\">\n  <span>\n  Exploring built-in ControlValueAccessors\n  <\/span>\n  <a href=\"#exploring-built-in-controlvalueaccessors\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><p>These are the built-in value accessors that Angular provides us with:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-tsx\" data-lang=\"tsx\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">BUILTIN_ACCESSORS<\/span> <span style=\"color:#f92672\">=<\/span> [\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">CheckboxControlValueAccessor<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">RangeValueAccessor<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">NumberValueAccessor<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">SelectControlValueAccessor<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">SelectMultipleControlValueAccessor<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">RadioControlValueAccessor<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>];\n<\/span><\/span><\/code><\/pre><\/div><p>In the upcoming sections we are going to explore the internals of some of the built-in value accessors.<\/p>\n<h3 id=\"selectvalueaccessor\">\n  <span>\n  <code>SelectValueAccessor<\/code>\n  <\/span>\n  <a href=\"#selectvalueaccessor\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h3><p>We can use this value accessor in 2 ways: by using either <code>[value]<\/code> or <code>[ngValue]<\/code>.<\/p>\n<h4 id=\"using-option-valueprimitivevalue\">\n  <span>\n  Using <code>&lt;option [value]=&quot;primitiveValue&quot;&gt;<\/code>\n  <\/span>\n  <a href=\"#using-option-valueprimitivevalue\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h4><p>The <code>primitiveValue<\/code> argument, as its name implies, can&rsquo;t be something else than a <strong>primitive value<\/strong>. If you&rsquo;d like to bind an object, <code>[ngValue]<\/code> should be your choice.<\/p>\n<p>Each <code>&lt;option&gt;<\/code> will set its value to <code>primitiveValue<\/code>.<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-tsx\" data-lang=\"tsx\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">@Input<\/span>(<span style=\"color:#e6db74\">&#39;value&#39;<\/span>)\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">set<\/span> <span style=\"color:#a6e22e\">value<\/span>(<span style=\"color:#a6e22e\">value<\/span>: <span style=\"color:#66d9ef\">any<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">_setElementValue<\/span>(<span style=\"color:#a6e22e\">value<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">_setElementValue<\/span>(<span style=\"color:#a6e22e\">value<\/span>: <span style=\"color:#66d9ef\">string<\/span>)<span style=\"color:#f92672\">:<\/span> <span style=\"color:#66d9ef\">void<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">_renderer<\/span>.<span style=\"color:#a6e22e\">setProperty<\/span>(<span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">_element<\/span>.<span style=\"color:#a6e22e\">nativeElement<\/span>, <span style=\"color:#e6db74\">&#39;value&#39;<\/span>, <span style=\"color:#a6e22e\">value<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p><em><a href=\"https:\/\/ng-run.com\/edit\/Xx0irFLVo4FdueEBtSAF?open=app%2Fselect-example.component.ts\" target=\"_blank\" rel=\"noopener\">ng-run Example.<\/a><\/em><\/p>\n<h4 id=\"using-option-ngvalueprimitiveornonprimitivevalue\">\n  <span>\n  Using <code>&lt;option [ngValue]=&quot;primitiveOrNonPrimitiveValue&quot;&gt;<\/code>\n  <\/span>\n  <a href=\"#using-option-ngvalueprimitiveornonprimitivevalue\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h4><p>Unlike <code>[value]<\/code>, <code>[ngValue]<\/code> can take both <strong>primitives<\/strong> and <strong>non-primitives<\/strong> as arguments.<\/p>\n<p>It will set the value of the <code>&lt;option&gt;<\/code> tag depending on the value provided to <code>[ngValue]<\/code>.<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-tsx\" data-lang=\"tsx\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">@Input<\/span>(<span style=\"color:#e6db74\">&#39;ngValue&#39;<\/span>)\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">set<\/span> <span style=\"color:#a6e22e\">ngValue<\/span>(<span style=\"color:#a6e22e\">value<\/span>: <span style=\"color:#66d9ef\">any<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">_select<\/span> <span style=\"color:#f92672\">==<\/span> <span style=\"color:#66d9ef\">null<\/span>) <span style=\"color:#66d9ef\">return<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">_select<\/span>.<span style=\"color:#a6e22e\">_optionMap<\/span>.<span style=\"color:#66d9ef\">set<\/span>(<span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">id<\/span>, <span style=\"color:#a6e22e\">value<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">_setElementValue<\/span>(<span style=\"color:#a6e22e\">_buildValueString<\/span>(<span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">id<\/span>, <span style=\"color:#a6e22e\">value<\/span>));\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">_select<\/span>.<span style=\"color:#a6e22e\">writeValue<\/span>(<span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">_select<\/span>.<span style=\"color:#a6e22e\">value<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/* ... *\/<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">function<\/span> <span style=\"color:#a6e22e\">_buildValueString<\/span>(<span style=\"color:#a6e22e\">id<\/span>: <span style=\"color:#66d9ef\">string<\/span> <span style=\"color:#f92672\">|<\/span> <span style=\"color:#66d9ef\">null<\/span>, <span style=\"color:#a6e22e\">value<\/span>: <span style=\"color:#66d9ef\">any<\/span>)<span style=\"color:#f92672\">:<\/span> <span style=\"color:#66d9ef\">string<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#a6e22e\">id<\/span> <span style=\"color:#f92672\">==<\/span> <span style=\"color:#66d9ef\">null<\/span>) <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#e6db74\">`<\/span><span style=\"color:#e6db74\">${<\/span><span style=\"color:#a6e22e\">value<\/span><span style=\"color:#e6db74\">}<\/span><span style=\"color:#e6db74\">`<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#a6e22e\">value<\/span> <span style=\"color:#f92672\">&amp;&amp;<\/span> <span style=\"color:#66d9ef\">typeof<\/span> <span style=\"color:#a6e22e\">value<\/span> <span style=\"color:#f92672\">===<\/span> <span style=\"color:#e6db74\">&#39;object&#39;<\/span>) <span style=\"color:#a6e22e\">value<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#e6db74\">&#39;Object&#39;<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#e6db74\">`<\/span><span style=\"color:#e6db74\">${<\/span><span style=\"color:#a6e22e\">id<\/span><span style=\"color:#e6db74\">}<\/span><span style=\"color:#e6db74\">: <\/span><span style=\"color:#e6db74\">${<\/span><span style=\"color:#a6e22e\">value<\/span><span style=\"color:#e6db74\">}<\/span><span style=\"color:#e6db74\">`<\/span>.<span style=\"color:#a6e22e\">slice<\/span>(<span style=\"color:#ae81ff\">0<\/span>, <span style=\"color:#ae81ff\">50<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p>We can see that if we pass an object, the value will be something like <code>'1: Object'<\/code>. If we pass a primitive value, like the name of a city, the will be: <code>0: 'NY'<\/code>.<\/p>\n<p>It is important to notice that when you change the value of the <code>&lt;select&gt;<\/code>(by using <code>FormControl.setValue(arg)<\/code>), if <code>arg<\/code> is an object, you must make sure it is the same object that you&rsquo;ve passed to <code>&lt;option [ngValue]=&quot;arg&quot;&gt;&lt;\/option&gt;<\/code>. That&rsquo;s because, by default, <code>SelectControlValueAccessor.writeValue(obj)<\/code>, it will use the <code>===<\/code> to identify the selected <code>option<\/code>.<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-tsx\" data-lang=\"tsx\"><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">writeValue<\/span>(<span style=\"color:#a6e22e\">value<\/span>: <span style=\"color:#66d9ef\">any<\/span>)<span style=\"color:#f92672\">:<\/span> <span style=\"color:#66d9ef\">void<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">value<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">value<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">id<\/span>: <span style=\"color:#66d9ef\">string<\/span><span style=\"color:#f92672\">|<\/span><span style=\"color:#66d9ef\">null<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">_getOptionId<\/span>(<span style=\"color:#a6e22e\">value<\/span>); <span style=\"color:#75715e\">\/\/ &lt;---- Here!\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>    <span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#a6e22e\">id<\/span> <span style=\"color:#f92672\">==<\/span> <span style=\"color:#66d9ef\">null<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">_renderer<\/span>.<span style=\"color:#a6e22e\">setProperty<\/span>(<span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">_elementRef<\/span>.<span style=\"color:#a6e22e\">nativeElement<\/span>, <span style=\"color:#e6db74\">&#39;selectedIndex&#39;<\/span>, <span style=\"color:#f92672\">-<\/span><span style=\"color:#ae81ff\">1<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>    }\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">valueString<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">_buildValueString<\/span>(<span style=\"color:#a6e22e\">id<\/span>, <span style=\"color:#a6e22e\">value<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">_renderer<\/span>.<span style=\"color:#a6e22e\">setProperty<\/span>(<span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">_elementRef<\/span>.<span style=\"color:#a6e22e\">nativeElement<\/span>, <span style=\"color:#e6db74\">&#39;value&#39;<\/span>, <span style=\"color:#a6e22e\">valueString<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">_getOptionId<\/span>(<span style=\"color:#a6e22e\">value<\/span>: <span style=\"color:#66d9ef\">any<\/span>)<span style=\"color:#f92672\">:<\/span> <span style=\"color:#66d9ef\">string<\/span><span style=\"color:#f92672\">|<\/span><span style=\"color:#66d9ef\">null<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">for<\/span> (<span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">id<\/span> <span style=\"color:#66d9ef\">of<\/span> Array.<span style=\"color:#66d9ef\">from<\/span>(<span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">_optionMap<\/span>.<span style=\"color:#a6e22e\">keys<\/span>())) {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">_compareWith<\/span>(<span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">_optionMap<\/span>.<span style=\"color:#66d9ef\">get<\/span>(<span style=\"color:#a6e22e\">id<\/span>), <span style=\"color:#a6e22e\">value<\/span>)) <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#a6e22e\">id<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>  }\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#66d9ef\">null<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p>Where <code>_compareWith<\/code> looks like this(by default):<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-tsx\" data-lang=\"tsx\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#a6e22e\">a<\/span> <span style=\"color:#f92672\">===<\/span> <span style=\"color:#a6e22e\">b<\/span> <span style=\"color:#f92672\">||<\/span> <span style=\"color:#66d9ef\">typeof<\/span> <span style=\"color:#a6e22e\">a<\/span> <span style=\"color:#f92672\">===<\/span> <span style=\"color:#e6db74\">&#39;number&#39;<\/span> <span style=\"color:#f92672\">&amp;&amp;<\/span> <span style=\"color:#66d9ef\">typeof<\/span> <span style=\"color:#a6e22e\">b<\/span> <span style=\"color:#f92672\">===<\/span> <span style=\"color:#e6db74\">&#39;number&#39;<\/span> <span style=\"color:#f92672\">&amp;&amp;<\/span> isNaN(<span style=\"color:#a6e22e\">a<\/span>) <span style=\"color:#f92672\">&amp;&amp;<\/span> isNaN(<span style=\"color:#a6e22e\">b<\/span>);\n<\/span><\/span><\/code><\/pre><\/div><p>Here&rsquo;s a <em><a href=\"https:\/\/stackblitz.com\/edit\/select-ng-value?file=src%2Fapp%2Fapp.component.html\" target=\"_blank\" rel=\"noopener\">StackBlitz example<\/a><\/em> with a custom <code>_compareWith<\/code> function:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-tsx\" data-lang=\"tsx\"><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">compareWith<\/span>(<span style=\"color:#a6e22e\">existing<\/span>, <span style=\"color:#a6e22e\">toCheckAgainst<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#f92672\">!<\/span><span style=\"color:#a6e22e\">toCheckAgainst<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#66d9ef\">false<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>  }\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#a6e22e\">existing<\/span>.<span style=\"color:#a6e22e\">id<\/span> <span style=\"color:#f92672\">===<\/span> <span style=\"color:#a6e22e\">toCheckAgainst<\/span>.<span style=\"color:#a6e22e\">id<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-html\" data-lang=\"html\"><span style=\"display:flex;\"><span><span style=\"color:#75715e\">&lt;!-- \n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">  1) Try without &#39;[compareWith]=&#34;compareWith&#34;&#39;\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">  2) select another option(`B`, or `C`)\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">  3) click `change`\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">  You should not see the value updated inside the `&lt;select&gt;`\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">  and that is because the default impl. of `compareWith` will compare the values with `===`\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">--&gt;<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>&lt;<span style=\"color:#f92672\">select<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#960050;background-color:#1e0010\">#<\/span><span style=\"color:#a6e22e\">s<\/span><span style=\"color:#f92672\">=<\/span><span style=\"color:#e6db74\">&#34;ngModel&#34;<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#960050;background-color:#1e0010\">[<\/span><span style=\"color:#a6e22e\">ngModel<\/span><span style=\"color:#960050;background-color:#1e0010\">]=&#34;<\/span><span style=\"color:#a6e22e\">selectedItem<\/span><span style=\"color:#960050;background-color:#1e0010\">&#34;<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#960050;background-color:#1e0010\">[<\/span><span style=\"color:#a6e22e\">compareWith<\/span><span style=\"color:#960050;background-color:#1e0010\">]=&#34;<\/span><span style=\"color:#a6e22e\">compareWith<\/span><span style=\"color:#960050;background-color:#1e0010\">&#34;<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>&gt;\n<\/span><\/span><span style=\"display:flex;\"><span>  &lt;<span style=\"color:#f92672\">option<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#960050;background-color:#1e0010\">*<\/span><span style=\"color:#a6e22e\">ngFor<\/span><span style=\"color:#f92672\">=<\/span><span style=\"color:#e6db74\">&#34;let item of items&#34;<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#960050;background-color:#1e0010\">[<\/span><span style=\"color:#a6e22e\">ngValue<\/span><span style=\"color:#960050;background-color:#1e0010\">]=&#34;<\/span><span style=\"color:#a6e22e\">item<\/span><span style=\"color:#960050;background-color:#1e0010\">&#34;<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>  &gt;\n<\/span><\/span><span style=\"display:flex;\"><span>    {{item.name}}\n<\/span><\/span><span style=\"display:flex;\"><span>  &lt;\/<span style=\"color:#f92672\">option<\/span>&gt;\n<\/span><\/span><span style=\"display:flex;\"><span>&lt;\/<span style=\"color:#f92672\">select<\/span>&gt;\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>&lt;<span style=\"color:#f92672\">br<\/span>&gt;&lt;<span style=\"color:#f92672\">br<\/span>&gt;\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>&lt;<span style=\"color:#f92672\">button<\/span> <span style=\"color:#960050;background-color:#1e0010\">(<\/span><span style=\"color:#a6e22e\">click<\/span><span style=\"color:#960050;background-color:#1e0010\">)=&#34;<\/span><span style=\"color:#a6e22e\">s<\/span><span style=\"color:#960050;background-color:#1e0010\">.<\/span><span style=\"color:#a6e22e\">control<\/span><span style=\"color:#960050;background-color:#1e0010\">.<\/span><span style=\"color:#a6e22e\">setValue<\/span><span style=\"color:#960050;background-color:#1e0010\">({<\/span> <span style=\"color:#a6e22e\">id:<\/span> <span style=\"color:#960050;background-color:#1e0010\">&#39;<\/span><span style=\"color:#a6e22e\">1<\/span><span style=\"color:#960050;background-color:#1e0010\">&#39;,<\/span> <span style=\"color:#a6e22e\">name:<\/span> <span style=\"color:#960050;background-color:#1e0010\">&#39;<\/span><span style=\"color:#a6e22e\">A<\/span><span style=\"color:#960050;background-color:#1e0010\">&#39;<\/span> <span style=\"color:#960050;background-color:#1e0010\">})&#34;<\/span>&gt;change&lt;\/<span style=\"color:#f92672\">button<\/span>&gt;\n<\/span><\/span><\/code><\/pre><\/div><p><em><a href=\"https:\/\/github.com\/angular\/angular\/blob\/master\/packages\/forms\/test\/value_accessor_integration_spec.ts#L216-L240\" target=\"_blank\" rel=\"noopener\">Here<\/a><\/em> is the test case for such behavior.<\/p>\n<h3 id=\"selectmultiplevalueaccessor\">\n  <span>\n  <code>SelectMultipleValueAccessor<\/code>\n  <\/span>\n  <a href=\"#selectmultiplevalueaccessor\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h3><p>Each option is tracked(added to the internal <code>_optionMap<\/code> property), because when a <strong>change event<\/strong> occurs on the <code>&lt;select&gt;<\/code>, the value accessor needs to provide the right values(the value provided to <code>[value]<\/code> or <code>[ngValue]<\/code> in <code>&lt;option&gt;<\/code>) to the model; this can be achieved with iterating over the selected options(<code>event.target.selectedOptions<\/code>) and retrieve their values from <code>_optionMap<\/code>.<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-tsx\" data-lang=\"tsx\"><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ _ - the select element\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span><span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">onChange<\/span> <span style=\"color:#f92672\">=<\/span> (<span style=\"color:#a6e22e\">_<\/span>: <span style=\"color:#66d9ef\">any<\/span>) <span style=\"color:#f92672\">=&gt;<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">selected<\/span>: <span style=\"color:#66d9ef\">Array<\/span>&lt;<span style=\"color:#f92672\">any<\/span>&gt; <span style=\"color:#f92672\">=<\/span> [];\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#a6e22e\">_<\/span>.<span style=\"color:#a6e22e\">hasOwnProperty<\/span>(<span style=\"color:#e6db74\">&#39;selectedOptions&#39;<\/span>)) {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">options<\/span>: <span style=\"color:#66d9ef\">HTMLCollection<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">_<\/span>.<span style=\"color:#a6e22e\">selectedOptions<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">for<\/span> (<span style=\"color:#66d9ef\">let<\/span> <span style=\"color:#a6e22e\">i<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#ae81ff\">0<\/span>; <span style=\"color:#a6e22e\">i<\/span> <span style=\"color:#f92672\">&lt;<\/span> <span style=\"color:#a6e22e\">options<\/span>.<span style=\"color:#a6e22e\">length<\/span>; <span style=\"color:#a6e22e\">i<\/span><span style=\"color:#f92672\">++<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">opt<\/span>: <span style=\"color:#66d9ef\">any<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">options<\/span>.<span style=\"color:#a6e22e\">item<\/span>(<span style=\"color:#a6e22e\">i<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">val<\/span>: <span style=\"color:#66d9ef\">any<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">_getOptionValue<\/span>(<span style=\"color:#a6e22e\">opt<\/span>.<span style=\"color:#a6e22e\">value<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#a6e22e\">selected<\/span>.<span style=\"color:#a6e22e\">push<\/span>(<span style=\"color:#a6e22e\">val<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>    }\n<\/span><\/span><span style=\"display:flex;\"><span>  }\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">value<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">selected<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">fn<\/span>(<span style=\"color:#a6e22e\">selected<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>};\n<\/span><\/span><\/code><\/pre><\/div><p>when value of the <code>FormControl<\/code> bound to the <code>&lt;select&gt;<\/code> element is changed programmatically(<code>FormControl.setValue()<\/code>), it needs to somehow determine which of the existing options match with the new provided values<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-tsx\" data-lang=\"tsx\"><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">writeValue<\/span>(<span style=\"color:#a6e22e\">value<\/span>: <span style=\"color:#66d9ef\">any<\/span>)<span style=\"color:#f92672\">:<\/span> <span style=\"color:#66d9ef\">void<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">value<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">value<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">let<\/span> <span style=\"color:#a6e22e\">optionSelectedStateSetter<\/span><span style=\"color:#f92672\">:<\/span> (<span style=\"color:#a6e22e\">opt<\/span>: <span style=\"color:#66d9ef\">\u0275NgSelectMultipleOption<\/span>, <span style=\"color:#a6e22e\">o<\/span>: <span style=\"color:#66d9ef\">any<\/span>) <span style=\"color:#f92672\">=&gt;<\/span> <span style=\"color:#66d9ef\">void<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">if<\/span> (Array.<span style=\"color:#a6e22e\">isArray<\/span>(<span style=\"color:#a6e22e\">value<\/span>)) {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#75715e\">\/\/ convert values to ids\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>    <span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">ids<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">value<\/span>.<span style=\"color:#a6e22e\">map<\/span>((<span style=\"color:#a6e22e\">v<\/span>) <span style=\"color:#f92672\">=&gt;<\/span> <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">_getOptionId<\/span>(<span style=\"color:#a6e22e\">v<\/span>));\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">optionSelectedStateSetter<\/span> <span style=\"color:#f92672\">=<\/span> (<span style=\"color:#a6e22e\">opt<\/span>, <span style=\"color:#a6e22e\">o<\/span>) <span style=\"color:#f92672\">=&gt;<\/span> { <span style=\"color:#a6e22e\">opt<\/span>.<span style=\"color:#a6e22e\">_setSelected<\/span>(<span style=\"color:#a6e22e\">ids<\/span>.<span style=\"color:#a6e22e\">indexOf<\/span>(<span style=\"color:#a6e22e\">o<\/span>.<span style=\"color:#a6e22e\">toString<\/span>()) <span style=\"color:#f92672\">&gt;<\/span> <span style=\"color:#f92672\">-<\/span><span style=\"color:#ae81ff\">1<\/span>); };\n<\/span><\/span><span style=\"display:flex;\"><span>  } <span style=\"color:#66d9ef\">else<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">optionSelectedStateSetter<\/span> <span style=\"color:#f92672\">=<\/span> (<span style=\"color:#a6e22e\">opt<\/span>, <span style=\"color:#a6e22e\">o<\/span>) <span style=\"color:#f92672\">=&gt;<\/span> { <span style=\"color:#a6e22e\">opt<\/span>.<span style=\"color:#a6e22e\">_setSelected<\/span>(<span style=\"color:#66d9ef\">false<\/span>); };\n<\/span><\/span><span style=\"display:flex;\"><span>  }\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">_optionMap<\/span>.<span style=\"color:#a6e22e\">forEach<\/span>(<span style=\"color:#a6e22e\">optionSelectedStateSetter<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><h3 id=\"radiovalueaccessor\">\n  <span>\n  <code>RadioValueAccessor<\/code>\n  <\/span>\n  <a href=\"#radiovalueaccessor\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h3><p>This value accessor keeps track of the radio buttons with the help of an internal service: <code>RadioControlRegistry<\/code>, which holds an array of <code>[NgControl, RadioValueAccessor]<\/code> pairs, where <code>NgControl<\/code> is a provider token that maps to one of the form-control-based directives: <code>NgModel<\/code>, <code>FormControl<\/code>, <code>FormControlName<\/code>.<\/p>\n<p>Let&rsquo;s see how it actually works:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-tsx\" data-lang=\"tsx\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">@Injectable<\/span>()\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">export<\/span> <span style=\"color:#66d9ef\">class<\/span> <span style=\"color:#a6e22e\">RadioControlRegistry<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">private<\/span> <span style=\"color:#a6e22e\">_accessors<\/span>: <span style=\"color:#66d9ef\">any<\/span>[] <span style=\"color:#f92672\">=<\/span> [];\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">add<\/span>(<span style=\"color:#a6e22e\">control<\/span>: <span style=\"color:#66d9ef\">NgControl<\/span>, <span style=\"color:#a6e22e\">accessor<\/span>: <span style=\"color:#66d9ef\">RadioControlValueAccessor<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">_accessors<\/span>.<span style=\"color:#a6e22e\">push<\/span>([<span style=\"color:#a6e22e\">control<\/span>, <span style=\"color:#a6e22e\">accessor<\/span>]);\n<\/span><\/span><span style=\"display:flex;\"><span>  }\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">remove<\/span>(<span style=\"color:#a6e22e\">accessor<\/span>: <span style=\"color:#66d9ef\">RadioControlValueAccessor<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">for<\/span> (<span style=\"color:#66d9ef\">let<\/span> <span style=\"color:#a6e22e\">i<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">_accessors<\/span>.<span style=\"color:#a6e22e\">length<\/span> <span style=\"color:#f92672\">-<\/span> <span style=\"color:#ae81ff\">1<\/span>; <span style=\"color:#a6e22e\">i<\/span> <span style=\"color:#f92672\">&gt;=<\/span> <span style=\"color:#ae81ff\">0<\/span>; <span style=\"color:#f92672\">--<\/span><span style=\"color:#a6e22e\">i<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">_accessors<\/span>[<span style=\"color:#a6e22e\">i<\/span>][<span style=\"color:#ae81ff\">1<\/span>] <span style=\"color:#f92672\">===<\/span> <span style=\"color:#a6e22e\">accessor<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">_accessors<\/span>.<span style=\"color:#a6e22e\">splice<\/span>(<span style=\"color:#a6e22e\">i<\/span>, <span style=\"color:#ae81ff\">1<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#66d9ef\">return<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>      }\n<\/span><\/span><span style=\"display:flex;\"><span>    }\n<\/span><\/span><span style=\"display:flex;\"><span>  }\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">select<\/span>(<span style=\"color:#a6e22e\">accessor<\/span>: <span style=\"color:#66d9ef\">RadioControlValueAccessor<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">_accessors<\/span>.<span style=\"color:#a6e22e\">forEach<\/span>((<span style=\"color:#a6e22e\">c<\/span>) <span style=\"color:#f92672\">=&gt;<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">_isSameGroup<\/span>(<span style=\"color:#a6e22e\">c<\/span>, <span style=\"color:#a6e22e\">accessor<\/span>) <span style=\"color:#f92672\">&amp;&amp;<\/span> <span style=\"color:#a6e22e\">c<\/span>[<span style=\"color:#ae81ff\">1<\/span>] <span style=\"color:#f92672\">!==<\/span> <span style=\"color:#a6e22e\">accessor<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#a6e22e\">c<\/span>[<span style=\"color:#ae81ff\">1<\/span>].<span style=\"color:#a6e22e\">fireUncheck<\/span>(<span style=\"color:#a6e22e\">accessor<\/span>.<span style=\"color:#a6e22e\">value<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>      }\n<\/span><\/span><span style=\"display:flex;\"><span>    });\n<\/span><\/span><span style=\"display:flex;\"><span>  }\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">private<\/span> <span style=\"color:#a6e22e\">_isSameGroup<\/span>(\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#a6e22e\">controlPair<\/span><span style=\"color:#f92672\">:<\/span> [<span style=\"color:#a6e22e\">NgControl<\/span>, <span style=\"color:#a6e22e\">RadioControlValueAccessor<\/span>],\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#a6e22e\">accessor<\/span>: <span style=\"color:#66d9ef\">RadioControlValueAccessor<\/span>)<span style=\"color:#f92672\">:<\/span> <span style=\"color:#66d9ef\">boolean<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#f92672\">!<\/span><span style=\"color:#a6e22e\">controlPair<\/span>[<span style=\"color:#ae81ff\">0<\/span>].<span style=\"color:#a6e22e\">control<\/span>) <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#66d9ef\">false<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#a6e22e\">controlPair<\/span>[<span style=\"color:#ae81ff\">0<\/span>].<span style=\"color:#a6e22e\">_parent<\/span> <span style=\"color:#f92672\">===<\/span> <span style=\"color:#a6e22e\">accessor<\/span>.<span style=\"color:#a6e22e\">_control<\/span>.<span style=\"color:#a6e22e\">_parent<\/span> <span style=\"color:#f92672\">&amp;&amp;<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#a6e22e\">controlPair<\/span>[<span style=\"color:#ae81ff\">1<\/span>].<span style=\"color:#a6e22e\">name<\/span> <span style=\"color:#f92672\">===<\/span> <span style=\"color:#a6e22e\">accessor<\/span>.<span style=\"color:#a6e22e\">name<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>  }\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p>Keep your eyes on the <code>RadioControlRegistry._isSameGroup<\/code> method.<\/p>\n<p>Let&rsquo;s narrow it down with a simpler example:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-html\" data-lang=\"html\"><span style=\"display:flex;\"><span>&lt;<span style=\"color:#f92672\">form<\/span>&gt;\n<\/span><\/span><span style=\"display:flex;\"><span>  &lt;<span style=\"color:#f92672\">input<\/span> <span style=\"color:#a6e22e\">ngModel<\/span> <span style=\"color:#a6e22e\">name<\/span><span style=\"color:#f92672\">=<\/span><span style=\"color:#e6db74\">&#34;option&#34;<\/span> <span style=\"color:#a6e22e\">value<\/span><span style=\"color:#f92672\">=<\/span><span style=\"color:#e6db74\">&#34;value1&#34;<\/span> <span style=\"color:#a6e22e\">type<\/span><span style=\"color:#f92672\">=<\/span><span style=\"color:#e6db74\">&#34;radio&#34;<\/span>&gt; <span style=\"color:#75715e\">&lt;!-- #1 NgModel._parent = the top-level `FormGroup` which results from `&lt;form&gt;` --&gt;<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>  &lt;<span style=\"color:#f92672\">ng-container<\/span> <span style=\"color:#a6e22e\">ngModelGroup<\/span><span style=\"color:#f92672\">=<\/span><span style=\"color:#e6db74\">&#34;foo&#34;<\/span>&gt;\n<\/span><\/span><span style=\"display:flex;\"><span>    &lt;<span style=\"color:#f92672\">input<\/span> <span style=\"color:#a6e22e\">ngModel<\/span> <span style=\"color:#a6e22e\">name<\/span><span style=\"color:#f92672\">=<\/span><span style=\"color:#e6db74\">&#34;option&#34;<\/span> <span style=\"color:#a6e22e\">value<\/span><span style=\"color:#f92672\">=<\/span><span style=\"color:#e6db74\">&#34;value1&#34;<\/span> <span style=\"color:#a6e22e\">type<\/span><span style=\"color:#f92672\">=<\/span><span style=\"color:#e6db74\">&#34;radio&#34;<\/span>&gt; <span style=\"color:#75715e\">&lt;!-- #2 NgModel._parent = the sub-group `FormGroup` which results from `ngModelGroup` --&gt;<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>  &lt;\/<span style=\"color:#f92672\">ng-container<\/span>&gt;\n<\/span><\/span><span style=\"display:flex;\"><span>&lt;\/<span style=\"color:#f92672\">form<\/span>&gt;\n<\/span><\/span><\/code><\/pre><\/div><p><em>Note that both radio buttons have the same value!<\/em><\/p>\n<p>The <code>RadioControlRegistry._accessors<\/code> array would look like this:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-tsx\" data-lang=\"tsx\"><span style=\"display:flex;\"><span>[\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">NgControl<\/span>(<span style=\"color:#f92672\">-&gt;<\/span> <span style=\"color:#a6e22e\">NgModel<\/span>) <span style=\"color:#75715e\">\/* #1 *\/<\/span>, <span style=\"color:#a6e22e\">RadioControlValueAccessor<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">NgControl<\/span>(<span style=\"color:#f92672\">-&gt;<\/span> <span style=\"color:#a6e22e\">NgModel<\/span>) <span style=\"color:#75715e\">\/* #2 *\/<\/span>, <span style=\"color:#a6e22e\">RadioControlValueAccessor<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>]\n<\/span><\/span><\/code><\/pre><\/div><p>When the user clicks on the <strong>first<\/strong> radio button, this method from <code>RadioControlRegistry<\/code> will be executed:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-tsx\" data-lang=\"tsx\"><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">select<\/span>(<span style=\"color:#a6e22e\">accessor<\/span>: <span style=\"color:#66d9ef\">RadioControlValueAccessor<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">_accessors<\/span>.<span style=\"color:#a6e22e\">forEach<\/span>((<span style=\"color:#a6e22e\">c<\/span>) <span style=\"color:#f92672\">=&gt;<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">_isSameGroup<\/span>(<span style=\"color:#a6e22e\">c<\/span>, <span style=\"color:#a6e22e\">accessor<\/span>) <span style=\"color:#f92672\">&amp;&amp;<\/span> <span style=\"color:#a6e22e\">c<\/span>[<span style=\"color:#ae81ff\">1<\/span>] <span style=\"color:#f92672\">!==<\/span> <span style=\"color:#a6e22e\">accessor<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#a6e22e\">c<\/span>[<span style=\"color:#ae81ff\">1<\/span>].<span style=\"color:#a6e22e\">fireUncheck<\/span>(<span style=\"color:#a6e22e\">accessor<\/span>.<span style=\"color:#a6e22e\">value<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>    }\n<\/span><\/span><span style=\"display:flex;\"><span>  });\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p>where <code>accessor<\/code> will be the <code>RadioControlValueAccessor<\/code> that belongs to the first radio button.<\/p>\n<p>Here is once again the <code>_isSameGroup<\/code> method:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-tsx\" data-lang=\"tsx\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">private<\/span> <span style=\"color:#a6e22e\">_isSameGroup<\/span>(\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">controlPair<\/span><span style=\"color:#f92672\">:<\/span> [<span style=\"color:#a6e22e\">NgControl<\/span>, <span style=\"color:#a6e22e\">RadioControlValueAccessor<\/span>],\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">accessor<\/span>: <span style=\"color:#66d9ef\">RadioControlValueAccessor<\/span>)<span style=\"color:#f92672\">:<\/span> <span style=\"color:#66d9ef\">boolean<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#f92672\">!<\/span><span style=\"color:#a6e22e\">controlPair<\/span>[<span style=\"color:#ae81ff\">0<\/span>].<span style=\"color:#a6e22e\">control<\/span>) <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#66d9ef\">false<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#a6e22e\">controlPair<\/span>[<span style=\"color:#ae81ff\">0<\/span>].<span style=\"color:#a6e22e\">_parent<\/span> <span style=\"color:#f92672\">===<\/span> <span style=\"color:#a6e22e\">accessor<\/span>.<span style=\"color:#a6e22e\">_control<\/span>.<span style=\"color:#a6e22e\">_parent<\/span> <span style=\"color:#f92672\">&amp;&amp;<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#a6e22e\">controlPair<\/span>[<span style=\"color:#ae81ff\">1<\/span>].<span style=\"color:#a6e22e\">name<\/span> <span style=\"color:#f92672\">===<\/span> <span style=\"color:#a6e22e\">accessor<\/span>.<span style=\"color:#a6e22e\">name<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p><code>controlPair[0]._parent === accessor._control._parent<\/code> is what prevents the first radio button from affecting the second one.<\/p>\n<p>With the following example, if we click on the <strong>second button<\/strong>, the first one will be marked as checked.<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-html\" data-lang=\"html\"><span style=\"display:flex;\"><span>&lt;<span style=\"color:#f92672\">form<\/span>&gt;\n<\/span><\/span><span style=\"display:flex;\"><span>  &lt;<span style=\"color:#f92672\">input<\/span> <span style=\"color:#a6e22e\">ngModel<\/span> <span style=\"color:#a6e22e\">name<\/span><span style=\"color:#f92672\">=<\/span><span style=\"color:#e6db74\">&#34;option&#34;<\/span> <span style=\"color:#a6e22e\">value<\/span><span style=\"color:#f92672\">=<\/span><span style=\"color:#e6db74\">&#34;value1&#34;<\/span> <span style=\"color:#a6e22e\">type<\/span><span style=\"color:#f92672\">=<\/span><span style=\"color:#e6db74\">&#34;radio&#34;<\/span>&gt;\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>  &lt;<span style=\"color:#f92672\">input<\/span> <span style=\"color:#a6e22e\">ngModel<\/span> <span style=\"color:#a6e22e\">name<\/span><span style=\"color:#f92672\">=<\/span><span style=\"color:#e6db74\">&#34;option&#34;<\/span> <span style=\"color:#a6e22e\">value<\/span><span style=\"color:#f92672\">=<\/span><span style=\"color:#e6db74\">&#34;value1&#34;<\/span> <span style=\"color:#a6e22e\">type<\/span><span style=\"color:#f92672\">=<\/span><span style=\"color:#e6db74\">&#34;radio&#34;<\/span>&gt;\n<\/span><\/span><span style=\"display:flex;\"><span>&lt;\/<span style=\"color:#f92672\">form<\/span>&gt;\n<\/span><\/span><\/code><\/pre><\/div><p>That&rsquo;s because out of <code>N<\/code> radio buttons with the same <code>name<\/code> and <code>value<\/code> attributes, only one can be marked as checked. In this case, it is the last one that fulfills these conditions:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-tsx\" data-lang=\"tsx\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">_isSameGroup<\/span>(<span style=\"color:#a6e22e\">c<\/span>, <span style=\"color:#a6e22e\">accessor<\/span>) <span style=\"color:#f92672\">&amp;&amp;<\/span> <span style=\"color:#a6e22e\">c<\/span>[<span style=\"color:#ae81ff\">1<\/span>] <span style=\"color:#f92672\">!==<\/span> <span style=\"color:#a6e22e\">accessor<\/span>\n<\/span><\/span><\/code><\/pre><\/div><p>where <code>accessor<\/code> is the <code>RadioControlValueAccessor<\/code> of the selected radio button.<\/p>\n<p><em><a href=\"https:\/\/ng-run.com\/edit\/Xx0irFLVo4FdueEBtSAF?open=app%2Fradio-example.component.ts\" target=\"_blank\" rel=\"noopener\">ng-run Example.<\/a><\/em><\/p>\n<h2 id=\"a-better-understanding-of-the-abstractcontrol-tree\">\n  <span>\n  A better understanding of the <code>AbstractControl<\/code> tree\n  <\/span>\n  <a href=\"#a-better-understanding-of-the-abstractcontrol-tree\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><p>Throughout the article you might have noticed the phrase <code>AbstractControl<\/code> tree. Remember that <code>AbstractControl<\/code> is an abstract class and its concrete implementations are <code>FormControl<\/code>, <code>FormGroup<\/code> and <code>FormArray<\/code>.<\/p>\n<p>In order to make things more intuitive, we can visualize their connections as a tree structure.<\/p>\n<p>For instance, this<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-tsx\" data-lang=\"tsx\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">new<\/span> <span style=\"color:#a6e22e\">FormGroup<\/span>({\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">name<\/span>: <span style=\"color:#66d9ef\">new<\/span> <span style=\"color:#a6e22e\">FormControl<\/span>(<span style=\"color:#e6db74\">&#39;&#39;<\/span>),\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">address<\/span>: <span style=\"color:#66d9ef\">new<\/span> <span style=\"color:#a6e22e\">FormGroup<\/span>({\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">city<\/span>: <span style=\"color:#66d9ef\">new<\/span> <span style=\"color:#a6e22e\">FormControl<\/span>(<span style=\"color:#e6db74\">&#39;&#39;<\/span>),\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">street<\/span>: <span style=\"color:#66d9ef\">new<\/span> <span style=\"color:#a6e22e\">FormControl<\/span>(<span style=\"color:#e6db74\">&#39;&#39;<\/span>),\n<\/span><\/span><span style=\"display:flex;\"><span>  }),\n<\/span><\/span><span style=\"display:flex;\"><span>});\n<\/span><\/span><\/code><\/pre><\/div><p>can be pictured as follows:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-markdown\" data-lang=\"markdown\"><span style=\"display:flex;\"><span>FG\n<\/span><\/span><span style=\"display:flex;\"><span>  \/  \\\n<\/span><\/span><span style=\"display:flex;\"><span> FC  FG\n<\/span><\/span><span style=\"display:flex;\"><span>    \/  \\\n<\/span><\/span><span style=\"display:flex;\"><span>   FC  FC\n<\/span><\/span><\/code><\/pre><\/div><p>Using the above diagram we are going to understand how the tree is altered by common <code>AbstractControl<\/code> actions, such as <code>reset()<\/code>, <code>submit()<\/code>, <code>markAsDirty()<\/code>.<\/p>\n<blockquote>\n<p>I&rsquo;d recommend reading <a href=\"#base-entities\"><em>Base entities<\/em><\/a> before carrying on.<\/p>\n<\/blockquote>\n<h3 id=\"_pendingdirty-_pendingvalue-_pendingchange\">\n  <span>\n  <code>_pendingDirty<\/code>, <code>_pendingValue<\/code>, <code>_pendingChange<\/code>\n  <\/span>\n  <a href=\"#_pendingdirty-_pendingvalue-_pendingchange\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h3><p>These private properties of the <code>AbstractControl<\/code> class are details that you might not have to be concerned about. However, they play a significant role regarding the <code>AbstractControl<\/code> tree&rsquo;s effectiveness.<\/p>\n<p>These properties are encountered in the context of a <code>FormControl<\/code> because their values depend on the values that are sent from the view(from the <code>ControlValueAccessor<\/code>).<\/p>\n<h4 id=\"_pendingchange\">\n  <span>\n  <code>_pendingChange<\/code>\n  <\/span>\n  <a href=\"#_pendingchange\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h4><p>This property indicates whether or not the user has changed the <code>FormControl<\/code>&rsquo;s value.<\/p>\n<p>Suppose you have an <code>&lt;input ngModel name=&quot;name&quot; type=&quot;text&quot;&gt;<\/code> and the user types in it. As soon as that happens, the <code>ControlValueAccessor<\/code>&rsquo;s <code>onChange<\/code> function will be invoked. The function that has been assigned to <code>onChange<\/code> looks as follows:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-tsx\" data-lang=\"tsx\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">function<\/span> <span style=\"color:#a6e22e\">setUpViewChangePipeline<\/span>(<span style=\"color:#a6e22e\">control<\/span>: <span style=\"color:#66d9ef\">FormControl<\/span>, <span style=\"color:#a6e22e\">dir<\/span>: <span style=\"color:#66d9ef\">NgControl<\/span>)<span style=\"color:#f92672\">:<\/span> <span style=\"color:#66d9ef\">void<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">dir<\/span>.<span style=\"color:#a6e22e\">valueAccessor<\/span> <span style=\"color:#f92672\">!<\/span>.<span style=\"color:#a6e22e\">registerOnChange<\/span>((<span style=\"color:#a6e22e\">newValue<\/span>: <span style=\"color:#66d9ef\">any<\/span>) <span style=\"color:#f92672\">=&gt;<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">control<\/span>.<span style=\"color:#a6e22e\">_pendingValue<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">newValue<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">control<\/span>.<span style=\"color:#a6e22e\">_pendingChange<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">true<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">control<\/span>.<span style=\"color:#a6e22e\">_pendingDirty<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">true<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#a6e22e\">control<\/span>.<span style=\"color:#a6e22e\">updateOn<\/span> <span style=\"color:#f92672\">===<\/span> <span style=\"color:#e6db74\">&#39;change&#39;<\/span>) <span style=\"color:#a6e22e\">updateControl<\/span>(<span style=\"color:#a6e22e\">control<\/span>, <span style=\"color:#a6e22e\">dir<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>  });\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p><code>control._pendingChange = true<\/code> marks that the user has <strong>visibly interacted<\/strong> with the <code>&lt;input&gt;<\/code>.<\/p>\n<p>Why is this useful anyway? It is because you can set the event on which the <code>AbstractControl<\/code> updates itself(it defaults to <code>change<\/code>).You can se the <strong>update strategy<\/strong> through <code>_updateOn<\/code> property:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-tsx\" data-lang=\"tsx\"><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">_updateOn<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;change&#39;<\/span><span style=\"color:#f92672\">|<\/span><span style=\"color:#e6db74\">&#39;blur&#39;<\/span><span style=\"color:#f92672\">|<\/span><span style=\"color:#e6db74\">&#39;submit&#39;<\/span>;\n<\/span><\/span><\/code><\/pre><\/div><p>With this mind, what would happen if the <code>FormControl<\/code> has the update strategy set to <code>blur<\/code>, and the <code>blur<\/code> event occurs in the view, without the user typing anything in the <code>&lt;input&gt;<\/code>? In this case, <code>_pendingChange<\/code> prevents the tree from being redundantly traversed.<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-tsx\" data-lang=\"tsx\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">function<\/span> <span style=\"color:#a6e22e\">setUpBlurPipeline<\/span>(<span style=\"color:#a6e22e\">control<\/span>: <span style=\"color:#66d9ef\">FormControl<\/span>, <span style=\"color:#a6e22e\">dir<\/span>: <span style=\"color:#66d9ef\">NgControl<\/span>)<span style=\"color:#f92672\">:<\/span> <span style=\"color:#66d9ef\">void<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">dir<\/span>.<span style=\"color:#a6e22e\">valueAccessor<\/span> <span style=\"color:#f92672\">!<\/span>.<span style=\"color:#a6e22e\">registerOnTouched<\/span>(() <span style=\"color:#f92672\">=&gt;<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#75715e\">\/* ... *\/<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#a6e22e\">control<\/span>.<span style=\"color:#a6e22e\">updateOn<\/span> <span style=\"color:#f92672\">===<\/span> <span style=\"color:#e6db74\">&#39;blur&#39;<\/span> <span style=\"color:#f92672\">&amp;&amp;<\/span> <span style=\"color:#a6e22e\">control<\/span>.<span style=\"color:#a6e22e\">_pendingChange<\/span>) <span style=\"color:#a6e22e\">updateControl<\/span>(<span style=\"color:#a6e22e\">control<\/span>, <span style=\"color:#a6e22e\">dir<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#75715e\">\/* ... *\/<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>  });\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p>Had the user typed anything in the <code>&lt;input&gt;<\/code>, the <code>control._pendingChange<\/code> would&rsquo;ve been set to true. As a result, the <code>FormControl<\/code> and its <strong>ancestors<\/strong> would&rsquo;ve been updated when the blur event had occurred.<\/p>\n<h4 id=\"_pendingdirty\">\n  <span>\n  <code>_pendingDirty<\/code>\n  <\/span>\n  <a href=\"#_pendingdirty\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h4><p>A <code>FormControl<\/code> is considered <code>dirty<\/code> if the user has changed its value in the UI.<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-tsx\" data-lang=\"tsx\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">function<\/span> <span style=\"color:#a6e22e\">setUpViewChangePipeline<\/span>(<span style=\"color:#a6e22e\">control<\/span>: <span style=\"color:#66d9ef\">FormControl<\/span>, <span style=\"color:#a6e22e\">dir<\/span>: <span style=\"color:#66d9ef\">NgControl<\/span>)<span style=\"color:#f92672\">:<\/span> <span style=\"color:#66d9ef\">void<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">dir<\/span>.<span style=\"color:#a6e22e\">valueAccessor<\/span> <span style=\"color:#f92672\">!<\/span>.<span style=\"color:#a6e22e\">registerOnChange<\/span>((<span style=\"color:#a6e22e\">newValue<\/span>: <span style=\"color:#66d9ef\">any<\/span>) <span style=\"color:#f92672\">=&gt;<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#75715e\">\/* ... *\/<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">control<\/span>.<span style=\"color:#a6e22e\">_pendingChange<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">true<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">control<\/span>.<span style=\"color:#a6e22e\">_pendingDirty<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">true<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#a6e22e\">control<\/span>.<span style=\"color:#a6e22e\">updateOn<\/span> <span style=\"color:#f92672\">===<\/span> <span style=\"color:#e6db74\">&#39;change&#39;<\/span>) <span style=\"color:#a6e22e\">updateControl<\/span>(<span style=\"color:#a6e22e\">control<\/span>, <span style=\"color:#a6e22e\">dir<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>  });\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">function<\/span> <span style=\"color:#a6e22e\">updateControl<\/span>(<span style=\"color:#a6e22e\">control<\/span>: <span style=\"color:#66d9ef\">FormControl<\/span>, <span style=\"color:#a6e22e\">dir<\/span>: <span style=\"color:#66d9ef\">NgControl<\/span>)<span style=\"color:#f92672\">:<\/span> <span style=\"color:#66d9ef\">void<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#a6e22e\">control<\/span>.<span style=\"color:#a6e22e\">_pendingDirty<\/span>) <span style=\"color:#a6e22e\">control<\/span>.<span style=\"color:#a6e22e\">markAsDirty<\/span>();\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#75715e\">\/* ... *\/<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p>The callback registered in with <code>dir.valueAccessor!.registerOnChange(cb)<\/code> will be invoked by the <code>ControlValueAccessor<\/code>(which resides in the <strong>view layer<\/strong>) whenever the value the UI changed.<\/p>\n<p>The <code>AbstractControl.markedAsDirty<\/code> implementation looks like this:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-tsx\" data-lang=\"tsx\"><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">markAsDirty<\/span>(<span style=\"color:#a6e22e\">opts<\/span><span style=\"color:#f92672\">:<\/span> {<span style=\"color:#a6e22e\">onlySelf?<\/span>: <span style=\"color:#66d9ef\">boolean<\/span>} <span style=\"color:#f92672\">=<\/span> {})<span style=\"color:#f92672\">:<\/span> <span style=\"color:#66d9ef\">void<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>  (<span style=\"color:#66d9ef\">this<\/span> <span style=\"color:#66d9ef\">as<\/span>{<span style=\"color:#a6e22e\">pristine<\/span>: <span style=\"color:#66d9ef\">boolean<\/span>}).<span style=\"color:#a6e22e\">pristine<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">false<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">_parent<\/span> <span style=\"color:#f92672\">&amp;&amp;<\/span> <span style=\"color:#f92672\">!<\/span><span style=\"color:#a6e22e\">opts<\/span>.<span style=\"color:#a6e22e\">onlySelf<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">_parent<\/span>.<span style=\"color:#a6e22e\">markAsDirty<\/span>(<span style=\"color:#a6e22e\">opts<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>  }\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p>So, if a <code>FormControl<\/code> is marked as dirty(due to UI change), its ancestors will be updated accordingly(in this case, they will be marked as dirty).<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-markdown\" data-lang=\"markdown\"><span style=\"display:flex;\"><span>FG (3)\n<\/span><\/span><span style=\"display:flex;\"><span>  \/  \\\n<\/span><\/span><span style=\"display:flex;\"><span> FC  FG (2)\n<\/span><\/span><span style=\"display:flex;\"><span>    \/  \\\n<\/span><\/span><span style=\"display:flex;\"><span>   FC  FC (1)\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>(1).parent = (2)\n<\/span><\/span><span style=\"display:flex;\"><span>(2).parent = (3)\n<\/span><\/span><span style=\"display:flex;\"><span>(3).parent = null(root)\n<\/span><\/span><\/code><\/pre><\/div><p>Assuming <code>(1)<\/code> a <code>FormControl<\/code> bound to an <code>&lt;input&gt;<\/code> and the user has just typed in it, the above method will be invoked from the <code>updateControl<\/code> function: <code>control.markAsDirty()<\/code>, where <code>control<\/code> is <code>(1)<\/code>. This will propagate up to the root, the order being this: <code>(1) -&gt; (2) -&gt; (3)<\/code>. Thus, the entire tree will be marked as dirty!<\/p>\n<p>There is also an option to solely mark <code>(1)<\/code> as dirty: <code>(1).markedAsDirty({ onlySelf: true })<\/code>.<\/p>\n<p>Now you be wondering, what&rsquo;s the need of <code>_pendingDirty<\/code>, if the control&rsquo;s dirtiness will be changed as soon as the user types something in? This is because the default strategy defaults to <code>change<\/code>, but it can be changed to something else like <code>blur<\/code> or <code>submit<\/code>.<\/p>\n<p>For example, here&rsquo;s what happens when the <strong>blur event<\/strong> occurs in the view:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-tsx\" data-lang=\"tsx\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">function<\/span> <span style=\"color:#a6e22e\">setUpBlurPipeline<\/span>(<span style=\"color:#a6e22e\">control<\/span>: <span style=\"color:#66d9ef\">FormControl<\/span>, <span style=\"color:#a6e22e\">dir<\/span>: <span style=\"color:#66d9ef\">NgControl<\/span>)<span style=\"color:#f92672\">:<\/span> <span style=\"color:#66d9ef\">void<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">dir<\/span>.<span style=\"color:#a6e22e\">valueAccessor<\/span> <span style=\"color:#f92672\">!<\/span>.<span style=\"color:#a6e22e\">registerOnTouched<\/span>(() <span style=\"color:#f92672\">=&gt;<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#75715e\">\/* ... *\/<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#a6e22e\">control<\/span>.<span style=\"color:#a6e22e\">updateOn<\/span> <span style=\"color:#f92672\">===<\/span> <span style=\"color:#e6db74\">&#39;blur&#39;<\/span> <span style=\"color:#f92672\">&amp;&amp;<\/span> <span style=\"color:#a6e22e\">control<\/span>.<span style=\"color:#a6e22e\">_pendingChange<\/span>) <span style=\"color:#a6e22e\">updateControl<\/span>(<span style=\"color:#a6e22e\">control<\/span>, <span style=\"color:#a6e22e\">dir<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#75715e\">\/* ... *\/<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>  });\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><h4 id=\"_pendingvalue\">\n  <span>\n  <code>_pendingValue<\/code>\n  <\/span>\n  <a href=\"#_pendingvalue\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h4><p>You can think of the property as being the <em>freshest<\/em> value of a <code>FormControl<\/code>.<\/p>\n<p>Its value is set when the <code>ControlValueAccessor.onChange<\/code> is invoked, where <code>ControlValueAccessor.onChange<\/code> does this:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-tsx\" data-lang=\"tsx\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">function<\/span> <span style=\"color:#a6e22e\">setUpViewChangePipeline<\/span>(<span style=\"color:#a6e22e\">control<\/span>: <span style=\"color:#66d9ef\">FormControl<\/span>, <span style=\"color:#a6e22e\">dir<\/span>: <span style=\"color:#66d9ef\">NgControl<\/span>)<span style=\"color:#f92672\">:<\/span> <span style=\"color:#66d9ef\">void<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">dir<\/span>.<span style=\"color:#a6e22e\">valueAccessor<\/span> <span style=\"color:#f92672\">!<\/span>.<span style=\"color:#a6e22e\">registerOnChange<\/span>((<span style=\"color:#a6e22e\">newValue<\/span>: <span style=\"color:#66d9ef\">any<\/span>) <span style=\"color:#f92672\">=&gt;<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">control<\/span>.<span style=\"color:#a6e22e\">_pendingValue<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">newValue<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#75715e\">\/* ... *\/<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#a6e22e\">control<\/span>.<span style=\"color:#a6e22e\">updateOn<\/span> <span style=\"color:#f92672\">===<\/span> <span style=\"color:#e6db74\">&#39;change&#39;<\/span>) <span style=\"color:#a6e22e\">updateControl<\/span>(<span style=\"color:#a6e22e\">control<\/span>, <span style=\"color:#a6e22e\">dir<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>  });\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">function<\/span> <span style=\"color:#a6e22e\">updateControl<\/span>(<span style=\"color:#a6e22e\">control<\/span>: <span style=\"color:#66d9ef\">FormControl<\/span>, <span style=\"color:#a6e22e\">dir<\/span>: <span style=\"color:#66d9ef\">NgControl<\/span>)<span style=\"color:#f92672\">:<\/span> <span style=\"color:#66d9ef\">void<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#a6e22e\">control<\/span>.<span style=\"color:#a6e22e\">_pendingDirty<\/span>) <span style=\"color:#a6e22e\">control<\/span>.<span style=\"color:#a6e22e\">markAsDirty<\/span>();\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">control<\/span>.<span style=\"color:#a6e22e\">setValue<\/span>(<span style=\"color:#a6e22e\">control<\/span>.<span style=\"color:#a6e22e\">_pendingValue<\/span>, {<span style=\"color:#a6e22e\">emitModelToViewChange<\/span>: <span style=\"color:#66d9ef\">false<\/span>});\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">dir<\/span>.<span style=\"color:#a6e22e\">viewToModelUpdate<\/span>(<span style=\"color:#a6e22e\">control<\/span>.<span style=\"color:#a6e22e\">_pendingValue<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">control<\/span>.<span style=\"color:#a6e22e\">_pendingChange<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">false<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p>However, what is the difference between <code>_pendingValue<\/code> and <code>value<\/code>? <code>_pendingValue<\/code> is the most recent value, whereas value is the <code>value<\/code> that is visible to the <code>AbstractControl<\/code> tree. The <code>value<\/code> is not always equal to <code>_pendingValue<\/code> as the <code>FormControl<\/code> might have a different update strategy than <code>change<\/code>. Of course, the view layer can hold the most recent value, but it doesn&rsquo;t mean that the model layer can.<\/p>\n<p>For example, if the <code>FormControl<\/code>&rsquo;s update strategy is set to <code>submit<\/code>, the model&rsquo;s value(<code>FormControl.value<\/code>) won&rsquo;t be equal to <code>_pendingValue<\/code>(which is the value that reflects the view) until the submit event occurs.<\/p>\n<h3 id=\"abstractcontrolsetvalue-and-abstractcontrolpatchvalue\">\n  <span>\n  AbstractControl.setValue() and AbstractControl.patchValue()\n  <\/span>\n  <a href=\"#abstractcontrolsetvalue-and-abstractcontrolpatchvalue\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h3><div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-tsx\" data-lang=\"tsx\"><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ {FormGroup|FormArray}.setValue\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span><span style=\"color:#a6e22e\">setValue<\/span>(<span style=\"color:#a6e22e\">value<\/span><span style=\"color:#f92672\">:<\/span> {[<span style=\"color:#a6e22e\">key<\/span>: <span style=\"color:#66d9ef\">string<\/span>]<span style=\"color:#f92672\">:<\/span> <span style=\"color:#66d9ef\">any<\/span>}, <span style=\"color:#a6e22e\">options<\/span><span style=\"color:#f92672\">:<\/span> {<span style=\"color:#a6e22e\">onlySelf?<\/span>: <span style=\"color:#66d9ef\">boolean<\/span>, <span style=\"color:#a6e22e\">emitEvent?<\/span>: <span style=\"color:#66d9ef\">boolean<\/span>} <span style=\"color:#f92672\">=<\/span> {})<span style=\"color:#f92672\">:<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">void<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">_checkAllValuesPresent<\/span>(<span style=\"color:#a6e22e\">value<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>  Object.<span style=\"color:#a6e22e\">keys<\/span>(<span style=\"color:#a6e22e\">value<\/span>).<span style=\"color:#a6e22e\">forEach<\/span>(<span style=\"color:#a6e22e\">name<\/span> <span style=\"color:#f92672\">=&gt;<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">_throwIfControlMissing<\/span>(<span style=\"color:#a6e22e\">name<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">controls<\/span>[<span style=\"color:#a6e22e\">name<\/span>].<span style=\"color:#a6e22e\">setValue<\/span>(<span style=\"color:#a6e22e\">value<\/span>[<span style=\"color:#a6e22e\">name<\/span>], {<span style=\"color:#a6e22e\">onlySelf<\/span>: <span style=\"color:#66d9ef\">true<\/span>, <span style=\"color:#a6e22e\">emitEvent<\/span>: <span style=\"color:#66d9ef\">options.emitEvent<\/span>});\n<\/span><\/span><span style=\"display:flex;\"><span>  });\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">updateValueAndValidity<\/span>(<span style=\"color:#a6e22e\">options<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-tsx\" data-lang=\"tsx\"><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ {FormGroup|FormArray}.patchValue\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span><span style=\"color:#a6e22e\">patchValue<\/span>(<span style=\"color:#a6e22e\">value<\/span><span style=\"color:#f92672\">:<\/span> {[<span style=\"color:#a6e22e\">key<\/span>: <span style=\"color:#66d9ef\">string<\/span>]<span style=\"color:#f92672\">:<\/span> <span style=\"color:#66d9ef\">any<\/span>}, <span style=\"color:#a6e22e\">options<\/span><span style=\"color:#f92672\">:<\/span> {<span style=\"color:#a6e22e\">onlySelf?<\/span>: <span style=\"color:#66d9ef\">boolean<\/span>, <span style=\"color:#a6e22e\">emitEvent?<\/span>: <span style=\"color:#66d9ef\">boolean<\/span>} <span style=\"color:#f92672\">=<\/span> {})<span style=\"color:#f92672\">:<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">void<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>  Object.<span style=\"color:#a6e22e\">keys<\/span>(<span style=\"color:#a6e22e\">value<\/span>).<span style=\"color:#a6e22e\">forEach<\/span>(<span style=\"color:#a6e22e\">name<\/span> <span style=\"color:#f92672\">=&gt;<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">controls<\/span>[<span style=\"color:#a6e22e\">name<\/span>]) {\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">controls<\/span>[<span style=\"color:#a6e22e\">name<\/span>].<span style=\"color:#a6e22e\">patchValue<\/span>(<span style=\"color:#a6e22e\">value<\/span>[<span style=\"color:#a6e22e\">name<\/span>], {<span style=\"color:#a6e22e\">onlySelf<\/span>: <span style=\"color:#66d9ef\">true<\/span>, <span style=\"color:#a6e22e\">emitEvent<\/span>: <span style=\"color:#66d9ef\">options.emitEvent<\/span>});\n<\/span><\/span><span style=\"display:flex;\"><span>    }\n<\/span><\/span><span style=\"display:flex;\"><span>  });\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">updateValueAndValidity<\/span>(<span style=\"color:#a6e22e\">options<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p><code>AbstractControl.setValue<\/code> will <strong>require<\/strong> you to <strong>provide<\/strong> a <strong>value<\/strong> for <strong>all<\/strong> <strong>the<\/strong> <strong>existing controls,<\/strong> whereas <code>AbstractControl.patchValue<\/code> will allow you to provide <strong>values<\/strong> for <strong>any of the existing controls<\/strong>.\n<code>{FormGroup|FormArray}.setValue<\/code> will first check if you provided an object which contains of all the existing controls, then it will check if you provided any <strong>redundant<\/strong> controls(controls that are <strong>not<\/strong> among the existing ones).<\/p>\n<p>When calling <code>setValue\/patchValue<\/code>, if <code>AbstractControl<\/code> is <code>FormControl<\/code>, it will first update the <code>FormControl<\/code> instance, then its ancestors. Otherwise, it will first update its descendants, then its ancestors.<\/p>\n<p>Updating the ancestors can be avoided with <code>{ onlySelf: true }<\/code> passed as the second argument.<\/p>\n<p>Here&rsquo;s once again the first example:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-tsx\" data-lang=\"tsx\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">fg<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">new<\/span> <span style=\"color:#a6e22e\">FormGroup<\/span>({\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">name<\/span>: <span style=\"color:#66d9ef\">new<\/span> <span style=\"color:#a6e22e\">FormControl<\/span>(<span style=\"color:#e6db74\">&#39;&#39;<\/span>),\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">address<\/span>: <span style=\"color:#66d9ef\">new<\/span> <span style=\"color:#a6e22e\">FormGroup<\/span>({\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">city<\/span>: <span style=\"color:#66d9ef\">new<\/span> <span style=\"color:#a6e22e\">FormControl<\/span>(<span style=\"color:#e6db74\">&#39;&#39;<\/span>),\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">street<\/span>: <span style=\"color:#66d9ef\">new<\/span> <span style=\"color:#a6e22e\">FormControl<\/span>(<span style=\"color:#e6db74\">&#39;&#39;<\/span>),\n<\/span><\/span><span style=\"display:flex;\"><span>  }),\n<\/span><\/span><span style=\"display:flex;\"><span>});\n<\/span><\/span><\/code><\/pre><\/div><div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-markdown\" data-lang=\"markdown\"><span style=\"display:flex;\"><span>FG (4)\n<\/span><\/span><span style=\"display:flex;\"><span>  \/  \\\n<\/span><\/span><span style=\"display:flex;\"><span> FC  FG (3) - address \n<\/span><\/span><span style=\"display:flex;\"><span>    \/  \\\n<\/span><\/span><span style=\"display:flex;\"><span>   FC  FC\n<\/span><\/span><span style=\"display:flex;\"><span>   (1) (2)\n<\/span><\/span><\/code><\/pre><\/div><p>After performing<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-tsx\" data-lang=\"tsx\"><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">fg<\/span>.<span style=\"color:#66d9ef\">get<\/span>(<span style=\"color:#e6db74\">&#39;address&#39;<\/span>).<span style=\"color:#a6e22e\">setValue<\/span>({ <span style=\"color:#a6e22e\">city<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;city&#39;<\/span>, <span style=\"color:#a6e22e\">street<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;street&#39;<\/span> })\n<\/span><\/span><\/code><\/pre><\/div><p>It will first update <code>(1)<\/code> and <code>(2)<\/code>, then it will update the value and validity of their container(<code>3<\/code>) and then it will finally update its ancestors.<\/p>\n<h4 id=\"patchvalue-example\">\n  <span>\n  <code>patchValue<\/code> example\n  <\/span>\n  <a href=\"#patchvalue-example\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h4><div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-tsx\" data-lang=\"tsx\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">c<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">new<\/span> <span style=\"color:#a6e22e\">FormControl<\/span>(<span style=\"color:#e6db74\">&#39;&#39;<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">c2<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">new<\/span> <span style=\"color:#a6e22e\">FormControl<\/span>(<span style=\"color:#e6db74\">&#39;&#39;<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">a<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">new<\/span> <span style=\"color:#a6e22e\">FormArray<\/span>([<span style=\"color:#a6e22e\">c<\/span>, <span style=\"color:#a6e22e\">c2<\/span>]);\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">a<\/span>.<span style=\"color:#a6e22e\">patchValue<\/span>([<span style=\"color:#e6db74\">&#39;andrei&#39;<\/span>]);\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">console<\/span>.<span style=\"color:#a6e22e\">log<\/span>(<span style=\"color:#a6e22e\">a<\/span>.<span style=\"color:#a6e22e\">value<\/span>) <span style=\"color:#75715e\">\/\/ [&#39;andrei&#39;, &#39;&#39;]\n<\/span><\/span><\/span><\/code><\/pre><\/div><h4 id=\"setvalue-example\">\n  <span>\n  <code>setValue<\/code> example\n  <\/span>\n  <a href=\"#setvalue-example\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h4><div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-tsx\" data-lang=\"tsx\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">c1<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">new<\/span> <span style=\"color:#a6e22e\">FormControl<\/span>(<span style=\"color:#e6db74\">&#39;c1&#39;<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">c2<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">new<\/span> <span style=\"color:#a6e22e\">FormControl<\/span>(<span style=\"color:#e6db74\">&#39;c2&#39;<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">a<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">new<\/span> <span style=\"color:#a6e22e\">FormArray<\/span>([<span style=\"color:#a6e22e\">c1<\/span>, <span style=\"color:#a6e22e\">c2<\/span>]);\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">a<\/span>.<span style=\"color:#a6e22e\">setValue<\/span>([<span style=\"color:#e6db74\">&#39;c1-updated&#39;<\/span>, <span style=\"color:#e6db74\">&#39;c2-updated&#39;<\/span>, <span style=\"color:#e6db74\">&#39;c3&#39;<\/span>]); <span style=\"color:#75715e\">\/\/ Error: Cannot find form control at index 2\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span><span style=\"color:#a6e22e\">a<\/span>.<span style=\"color:#a6e22e\">setValue<\/span>([<span style=\"color:#e6db74\">&#39;c1-updated&#39;<\/span>]); <span style=\"color:#75715e\">\/\/ Error: Must supply a value for form control at index: 1\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">a<\/span>.<span style=\"color:#a6e22e\">setValue<\/span>([<span style=\"color:#e6db74\">&#39;c1-updated&#39;<\/span>, <span style=\"color:#e6db74\">&#39;c2-updated&#39;<\/span>]);\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">console<\/span>.<span style=\"color:#a6e22e\">log<\/span>(<span style=\"color:#a6e22e\">a<\/span>.<span style=\"color:#a6e22e\">value<\/span>); <span style=\"color:#75715e\">\/\/\u00a0[&#34;c1-updated&#34;, &#34;c2-updated&#34;]\n<\/span><\/span><\/span><\/code><\/pre><\/div><h2 id=\"what-happens-with-the-abstractcontrol-tree-on-submit\">\n  <span>\n  What happens with the <code>AbstractControl<\/code> tree on submit?\n  <\/span>\n  <a href=\"#what-happens-with-the-abstractcontrol-tree-on-submit\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><blockquote>\n<p>Only <code>FormGroupDirective<\/code> and <code>NgForm<\/code> can call <code>onSubmit<\/code>.<\/p>\n<\/blockquote>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-tsx\" data-lang=\"tsx\"><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">onSubmit<\/span>(<span style=\"color:#a6e22e\">$event<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>  (<span style=\"color:#66d9ef\">this<\/span> <span style=\"color:#66d9ef\">as<\/span>{<span style=\"color:#a6e22e\">submitted<\/span>: <span style=\"color:#66d9ef\">boolean<\/span>}).<span style=\"color:#a6e22e\">submitted<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">true<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">syncPendingControls<\/span>(<span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">form<\/span>, <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">directives<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">ngSubmit<\/span>.<span style=\"color:#a6e22e\">emit<\/span>(<span style=\"color:#a6e22e\">$event<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#66d9ef\">false<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p>Some <code>AbstractControl<\/code> instances might have set the option <code>updateOn<\/code> differently. Therefore, if one <code>FormControl<\/code> has the <code>updateOn<\/code> option set to submit, it means that its <strong>value<\/strong> <strong>and UI<\/strong> <strong>status(<\/strong><code>dirty<\/code>, <code>untouched<\/code> etc&hellip;) will only be updated when the submit event occurs. This is what <code>syncPendingControls()<\/code> does.<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-tsx\" data-lang=\"tsx\"><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ FormControl\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span><span style=\"color:#a6e22e\">_syncPendingControls<\/span>()<span style=\"color:#f92672\">:<\/span> <span style=\"color:#66d9ef\">boolean<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">updateOn<\/span> <span style=\"color:#f92672\">===<\/span> <span style=\"color:#e6db74\">&#39;submit&#39;<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">_pendingDirty<\/span>) <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">markAsDirty<\/span>();\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">_pendingTouched<\/span>) <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">markAsTouched<\/span>();\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">_pendingChange<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">setValue<\/span>(<span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">_pendingValue<\/span>, {<span style=\"color:#a6e22e\">onlySelf<\/span>: <span style=\"color:#66d9ef\">true<\/span>, <span style=\"color:#a6e22e\">emitModelToViewChange<\/span>: <span style=\"color:#66d9ef\">false<\/span>});\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#66d9ef\">true<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>    }\n<\/span><\/span><span style=\"display:flex;\"><span>  }\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#66d9ef\">false<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ FormArray - FormGroup works in a very similar fashion\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span><span style=\"color:#a6e22e\">_syncPendingControls<\/span>()<span style=\"color:#f92672\">:<\/span> <span style=\"color:#66d9ef\">boolean<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">let<\/span> <span style=\"color:#a6e22e\">subtreeUpdated<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">controls<\/span>.<span style=\"color:#a6e22e\">reduce<\/span>((<span style=\"color:#a6e22e\">updated<\/span>: <span style=\"color:#66d9ef\">boolean<\/span>, <span style=\"color:#a6e22e\">child<\/span>: <span style=\"color:#66d9ef\">AbstractControl<\/span>) <span style=\"color:#f92672\">=&gt;<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#a6e22e\">child<\/span>.<span style=\"color:#a6e22e\">_syncPendingControls<\/span>() <span style=\"color:#f92672\">?<\/span> <span style=\"color:#66d9ef\">true<\/span> <span style=\"color:#f92672\">:<\/span> <span style=\"color:#a6e22e\">updated<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>    }, <span style=\"color:#66d9ef\">false<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#a6e22e\">subtreeUpdated<\/span>) <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">updateValueAndValidity<\/span>({<span style=\"color:#a6e22e\">onlySelf<\/span>: <span style=\"color:#66d9ef\">true<\/span>});\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#a6e22e\">subtreeUpdated<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>  }\n<\/span><\/span><\/code><\/pre><\/div><p>Consider this example:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-tsx\" data-lang=\"tsx\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">form<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">fb<\/span>.<span style=\"color:#a6e22e\">group<\/span>({ <span style=\"color:#a6e22e\">name<\/span>: <span style=\"color:#66d9ef\">this.fb.control<\/span>(<span style=\"color:#e6db74\">&#39;&#39;<\/span>, { <span style=\"color:#a6e22e\">updateOn<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;submit&#39;<\/span> }) });\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">form<\/span>.<span style=\"color:#a6e22e\">valueChanges<\/span>.<span style=\"color:#a6e22e\">subscribe<\/span>(<span style=\"color:#a6e22e\">console<\/span>.<span style=\"color:#a6e22e\">warn<\/span>);\n<\/span><\/span><\/code><\/pre><\/div><p>When having a view like this<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-html\" data-lang=\"html\"><span style=\"display:flex;\"><span>&lt;<span style=\"color:#f92672\">form<\/span> <span style=\"color:#960050;background-color:#1e0010\">[<\/span><span style=\"color:#a6e22e\">formGroup<\/span><span style=\"color:#960050;background-color:#1e0010\">]=&#34;<\/span><span style=\"color:#a6e22e\">form<\/span><span style=\"color:#960050;background-color:#1e0010\">&#34;<\/span> <span style=\"color:#960050;background-color:#1e0010\">(<\/span><span style=\"color:#a6e22e\">ngSubmit<\/span><span style=\"color:#960050;background-color:#1e0010\">)=&#34;<\/span><span style=\"color:#a6e22e\">onSubmit<\/span><span style=\"color:#960050;background-color:#1e0010\">()&#34;<\/span>&gt;\n<\/span><\/span><span style=\"display:flex;\"><span>  &lt;<span style=\"color:#f92672\">input<\/span> <span style=\"color:#960050;background-color:#1e0010\">[<\/span><span style=\"color:#a6e22e\">formControl<\/span><span style=\"color:#960050;background-color:#1e0010\">]=&#34;<\/span><span style=\"color:#a6e22e\">form<\/span><span style=\"color:#960050;background-color:#1e0010\">.<\/span><span style=\"color:#a6e22e\">get<\/span><span style=\"color:#960050;background-color:#1e0010\">(&#39;<\/span><span style=\"color:#a6e22e\">name<\/span><span style=\"color:#960050;background-color:#1e0010\">&#39;)&#34;<\/span> <span style=\"color:#a6e22e\">type<\/span><span style=\"color:#f92672\">=<\/span><span style=\"color:#e6db74\">&#34;text&#34;<\/span>&gt;\n<\/span><\/span><span style=\"display:flex;\"><span>  &lt;<span style=\"color:#f92672\">button<\/span> <span style=\"color:#a6e22e\">type<\/span><span style=\"color:#f92672\">=<\/span><span style=\"color:#e6db74\">&#34;submit&#34;<\/span>&gt;Submit&lt;\/<span style=\"color:#f92672\">button<\/span>&gt;\n<\/span><\/span><span style=\"display:flex;\"><span>&lt;\/<span style=\"color:#f92672\">form<\/span>&gt;\n<\/span><\/span><\/code><\/pre><\/div><p>you get the <strong>same values every time<\/strong> the <code>submit<\/code> event occurs, whereas with this view<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-html\" data-lang=\"html\"><span style=\"display:flex;\"><span>&lt;<span style=\"color:#f92672\">form<\/span> <span style=\"color:#960050;background-color:#1e0010\">[<\/span><span style=\"color:#a6e22e\">formGroup<\/span><span style=\"color:#960050;background-color:#1e0010\">]=&#34;<\/span><span style=\"color:#a6e22e\">form<\/span><span style=\"color:#960050;background-color:#1e0010\">&#34;<\/span> <span style=\"color:#960050;background-color:#1e0010\">(<\/span><span style=\"color:#a6e22e\">ngSubmit<\/span><span style=\"color:#960050;background-color:#1e0010\">)=&#34;<\/span><span style=\"color:#a6e22e\">onSubmit<\/span><span style=\"color:#960050;background-color:#1e0010\">()&#34;<\/span>&gt;\n<\/span><\/span><span style=\"display:flex;\"><span>  &lt;<span style=\"color:#f92672\">input<\/span> <span style=\"color:#a6e22e\">formControlName<\/span><span style=\"color:#f92672\">=<\/span><span style=\"color:#e6db74\">&#34;name&#34;<\/span> <span style=\"color:#a6e22e\">type<\/span><span style=\"color:#f92672\">=<\/span><span style=\"color:#e6db74\">&#34;text&#34;<\/span>&gt;\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>  &lt;<span style=\"color:#f92672\">br<\/span>&gt;&lt;<span style=\"color:#f92672\">br<\/span>&gt;\n<\/span><\/span><span style=\"display:flex;\"><span>  &lt;<span style=\"color:#f92672\">button<\/span> <span style=\"color:#a6e22e\">type<\/span><span style=\"color:#f92672\">=<\/span><span style=\"color:#e6db74\">&#34;submit&#34;<\/span>&gt;Submit&lt;\/<span style=\"color:#f92672\">button<\/span>&gt;\n<\/span><\/span><span style=\"display:flex;\"><span>&lt;\/<span style=\"color:#f92672\">form<\/span>&gt;\n<\/span><\/span><\/code><\/pre><\/div><p>you get the <strong>values only once,<\/strong> when the <code>submit<\/code> event occurs.<\/p>\n<p>That&rsquo;s because of the way <code>FormControlName<\/code> directives work inside a <code>FormGroupDirective<\/code>. A <code>FormGroupDirective<\/code> will keep track of <code>FormControlName<\/code> directives with the help of directives property. When the <strong>submit<\/strong> event occurs, each <code>FormControlName<\/code> will set the <code>_pendingChange<\/code> property of their bound <code>FormControl<\/code> to false.<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-tsx\" data-lang=\"tsx\"><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">directives<\/span>.<span style=\"color:#a6e22e\">forEach<\/span>(<span style=\"color:#a6e22e\">dir<\/span> <span style=\"color:#f92672\">=&gt;<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">control<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">dir<\/span>.<span style=\"color:#a6e22e\">control<\/span> <span style=\"color:#66d9ef\">as<\/span> <span style=\"color:#a6e22e\">FormControl<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#a6e22e\">control<\/span>.<span style=\"color:#a6e22e\">updateOn<\/span> <span style=\"color:#f92672\">===<\/span> <span style=\"color:#e6db74\">&#39;submit&#39;<\/span> <span style=\"color:#f92672\">&amp;&amp;<\/span> <span style=\"color:#a6e22e\">control<\/span>.<span style=\"color:#a6e22e\">_pendingChange<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#75715e\">\/* ... *\/<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">control<\/span>.<span style=\"color:#a6e22e\">_pendingChange<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">false<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>  }\n<\/span><\/span><span style=\"display:flex;\"><span>});\n<\/span><\/span><\/code><\/pre><\/div><p><code>FormControl._pendingChange<\/code> is set to true every time the change event occurs in the UI.<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-tsx\" data-lang=\"tsx\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">function<\/span> <span style=\"color:#a6e22e\">setUpViewChangePipeline<\/span>(<span style=\"color:#a6e22e\">control<\/span>: <span style=\"color:#66d9ef\">FormControl<\/span>, <span style=\"color:#a6e22e\">dir<\/span>: <span style=\"color:#66d9ef\">NgControl<\/span>)<span style=\"color:#f92672\">:<\/span> <span style=\"color:#66d9ef\">void<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">dir<\/span>.<span style=\"color:#a6e22e\">valueAccessor<\/span> <span style=\"color:#f92672\">!<\/span>.<span style=\"color:#a6e22e\">registerOnChange<\/span>((<span style=\"color:#a6e22e\">newValue<\/span>: <span style=\"color:#66d9ef\">any<\/span>) <span style=\"color:#f92672\">=&gt;<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">control<\/span>.<span style=\"color:#a6e22e\">_pendingValue<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">newValue<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">control<\/span>.<span style=\"color:#a6e22e\">_pendingChange<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">true<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">control<\/span>.<span style=\"color:#a6e22e\">_pendingDirty<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">true<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#a6e22e\">control<\/span>.<span style=\"color:#a6e22e\">updateOn<\/span> <span style=\"color:#f92672\">===<\/span> <span style=\"color:#e6db74\">&#39;change&#39;<\/span>) <span style=\"color:#a6e22e\">updateControl<\/span>(<span style=\"color:#a6e22e\">control<\/span>, <span style=\"color:#a6e22e\">dir<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>  });\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p><em><a href=\"https:\/\/ng-run.com\/edit\/Xx0irFLVo4FdueEBtSAF?open=app%2Fsubmit-catch.component.ts\" target=\"_blank\" rel=\"noopener\">ng-run Example.<\/a><\/em><\/p>\n<h3 id=\"retrieving-abstractcontrols-from-the-tree\">\n  <span>\n  Retrieving <code>AbstractControls<\/code> from the tree\n  <\/span>\n  <a href=\"#retrieving-abstractcontrols-from-the-tree\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h3><div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-tsx\" data-lang=\"tsx\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">fg<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">new<\/span> <span style=\"color:#a6e22e\">FormGroup<\/span>({\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">name<\/span>: <span style=\"color:#66d9ef\">new<\/span> <span style=\"color:#a6e22e\">FormControl<\/span>(<span style=\"color:#e6db74\">&#39;&#39;<\/span>),\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">address<\/span>: <span style=\"color:#66d9ef\">new<\/span> <span style=\"color:#a6e22e\">FormGroup<\/span>({\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">city<\/span>: <span style=\"color:#66d9ef\">new<\/span> <span style=\"color:#a6e22e\">FormControl<\/span>(<span style=\"color:#e6db74\">&#39;&#39;<\/span>),\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">street<\/span>: <span style=\"color:#66d9ef\">new<\/span> <span style=\"color:#a6e22e\">FormControl<\/span>(<span style=\"color:#e6db74\">&#39;&#39;<\/span>),\n<\/span><\/span><span style=\"display:flex;\"><span>  }),\n<\/span><\/span><span style=\"display:flex;\"><span>});\n<\/span><\/span><\/code><\/pre><\/div><p>There are a couple of ways to retrieve an <code>AbstractControl<\/code>.\nIf the <code>AbstractControl<\/code> you want to retrieve is a direct descendant of a <strong>form control container<\/strong>(<code>fg<\/code> in this case), you can do this:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-tsx\" data-lang=\"tsx\"><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">fg<\/span>.<span style=\"color:#a6e22e\">controls<\/span>[<span style=\"color:#a6e22e\">nameOfCtrl<\/span>];\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ In our example\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span><span style=\"color:#a6e22e\">fg<\/span>.<span style=\"color:#a6e22e\">controls<\/span>[<span style=\"color:#e6db74\">&#39;name&#39;<\/span>]\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">fg<\/span>.<span style=\"color:#a6e22e\">controls<\/span>[<span style=\"color:#e6db74\">&#39;address&#39;<\/span>]\n<\/span><\/span><\/code><\/pre><\/div><p>However, if the <code>AbstractControl<\/code> is a few levels deep, you might find it annoying to write such things:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-tsx\" data-lang=\"tsx\"><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">fg<\/span>.<span style=\"color:#a6e22e\">controls<\/span>[<span style=\"color:#e6db74\">&#39;address&#39;<\/span>].<span style=\"color:#a6e22e\">controls<\/span>[<span style=\"color:#e6db74\">&#39;city&#39;<\/span>]\n<\/span><\/span><\/code><\/pre><\/div><p>You can use the <code>AbstractControl.get()<\/code> method instead<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-tsx\" data-lang=\"tsx\"><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">fg<\/span>.<span style=\"color:#66d9ef\">get<\/span>(<span style=\"color:#e6db74\">&#39;address.city&#39;<\/span>)\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ Or\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">fg<\/span>.<span style=\"color:#66d9ef\">get<\/span>([<span style=\"color:#e6db74\">&#39;address&#39;<\/span>, <span style=\"color:#e6db74\">&#39;street&#39;<\/span>])\n<\/span><\/span><\/code><\/pre><\/div><p><code>AbstractControl.get()<\/code> will internally call a function <code>_find<\/code> which will traverse the tree downwards based on the path provided.<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-tsx\" data-lang=\"tsx\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">function<\/span> <span style=\"color:#a6e22e\">_find<\/span>(<span style=\"color:#a6e22e\">control<\/span>: <span style=\"color:#66d9ef\">AbstractControl<\/span>, <span style=\"color:#a6e22e\">path<\/span>: <span style=\"color:#66d9ef\">Array<\/span>&lt;<span style=\"color:#f92672\">string<\/span><span style=\"color:#960050;background-color:#1e0010\">|<\/span><span style=\"color:#a6e22e\">number<\/span>&gt;<span style=\"color:#f92672\">|<\/span> <span style=\"color:#66d9ef\">string<\/span>, <span style=\"color:#a6e22e\">delimiter<\/span>: <span style=\"color:#66d9ef\">string<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#a6e22e\">path<\/span> <span style=\"color:#f92672\">==<\/span> <span style=\"color:#66d9ef\">null<\/span>) <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#66d9ef\">null<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#f92672\">!<\/span>(<span style=\"color:#a6e22e\">path<\/span> <span style=\"color:#66d9ef\">instanceof<\/span> Array)) {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">path<\/span> <span style=\"color:#f92672\">=<\/span> (&lt;<span style=\"color:#f92672\">string<\/span>&gt;<span style=\"color:#a6e22e\">path<\/span>).<span style=\"color:#a6e22e\">split<\/span>(<span style=\"color:#a6e22e\">delimiter<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>  }\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#a6e22e\">path<\/span> <span style=\"color:#66d9ef\">instanceof<\/span> Array <span style=\"color:#f92672\">&amp;&amp;<\/span> (<span style=\"color:#a6e22e\">path<\/span>.<span style=\"color:#a6e22e\">length<\/span> <span style=\"color:#f92672\">===<\/span> <span style=\"color:#ae81ff\">0<\/span>)) <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#66d9ef\">null<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">return<\/span> (&lt;<span style=\"color:#f92672\">Array<\/span><span style=\"color:#960050;background-color:#1e0010\">&lt;<\/span><span style=\"color:#a6e22e\">string<\/span><span style=\"color:#960050;background-color:#1e0010\">|<\/span><span style=\"color:#a6e22e\">number<\/span>&gt;<span style=\"color:#f92672\">&gt;<\/span><span style=\"color:#a6e22e\">path<\/span>).<span style=\"color:#a6e22e\">reduce<\/span>((<span style=\"color:#a6e22e\">v<\/span>: <span style=\"color:#66d9ef\">AbstractControl<\/span> <span style=\"color:#f92672\">|<\/span> <span style=\"color:#66d9ef\">null<\/span>, <span style=\"color:#a6e22e\">name<\/span>) <span style=\"color:#f92672\">=&gt;<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#a6e22e\">v<\/span> <span style=\"color:#66d9ef\">instanceof<\/span> <span style=\"color:#a6e22e\">FormGroup<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#a6e22e\">v<\/span>.<span style=\"color:#a6e22e\">controls<\/span>.<span style=\"color:#a6e22e\">hasOwnProperty<\/span>(<span style=\"color:#a6e22e\">name<\/span> <span style=\"color:#66d9ef\">as<\/span> <span style=\"color:#66d9ef\">string<\/span>) <span style=\"color:#f92672\">?<\/span> <span style=\"color:#a6e22e\">v<\/span>.<span style=\"color:#a6e22e\">controls<\/span>[<span style=\"color:#a6e22e\">name<\/span>] <span style=\"color:#f92672\">:<\/span> <span style=\"color:#66d9ef\">null<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>    }\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#a6e22e\">v<\/span> <span style=\"color:#66d9ef\">instanceof<\/span> <span style=\"color:#a6e22e\">FormArray<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#a6e22e\">v<\/span>.<span style=\"color:#a6e22e\">at<\/span>(&lt;<span style=\"color:#f92672\">number<\/span>&gt;<span style=\"color:#a6e22e\">name<\/span>) <span style=\"color:#f92672\">||<\/span> <span style=\"color:#66d9ef\">null<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>    }\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#66d9ef\">null<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>  }, <span style=\"color:#a6e22e\">control<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p>As you might have noticed, if <code>fg<\/code> had been a <code>FormArray<\/code> instance, you could&rsquo;ve retrieved its descendants by specifying an <strong>index,<\/strong> as opposed to a <strong>property name<\/strong>(like you&rsquo;d do with <code>FormGroup<\/code>)<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-tsx\" data-lang=\"tsx\"><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">fg<\/span>.<span style=\"color:#66d9ef\">get<\/span>(<span style=\"color:#e6db74\">&#39;1.city&#39;<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ Or\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">fg<\/span>.<span style=\"color:#66d9ef\">get<\/span>([<span style=\"color:#e6db74\">&#39;1&#39;<\/span>, <span style=\"color:#e6db74\">&#39;city&#39;<\/span>]);\n<\/span><\/span><\/code><\/pre><\/div><h3 id=\"abstractcontrolupdatevalueandvalidity\">\n  <span>\n  <code>AbstractControl.updateValueAndValidity()<\/code>\n  <\/span>\n  <a href=\"#abstractcontrolupdatevalueandvalidity\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h3><div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-tsx\" data-lang=\"tsx\"><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">updateValueAndValidity<\/span>(<span style=\"color:#a6e22e\">opts<\/span><span style=\"color:#f92672\">:<\/span> {<span style=\"color:#a6e22e\">onlySelf?<\/span>: <span style=\"color:#66d9ef\">boolean<\/span>, <span style=\"color:#a6e22e\">emitEvent?<\/span>: <span style=\"color:#66d9ef\">boolean<\/span>} <span style=\"color:#f92672\">=<\/span> {})<span style=\"color:#f92672\">:<\/span> <span style=\"color:#66d9ef\">void<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">_setInitialStatus<\/span>();\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">_updateValue<\/span>();\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">enabled<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">_cancelExistingSubscription<\/span>();\n<\/span><\/span><span style=\"display:flex;\"><span>    (<span style=\"color:#66d9ef\">this<\/span> <span style=\"color:#66d9ef\">as<\/span>{<span style=\"color:#a6e22e\">errors<\/span>: <span style=\"color:#66d9ef\">ValidationErrors<\/span> <span style=\"color:#f92672\">|<\/span> <span style=\"color:#66d9ef\">null<\/span>}).<span style=\"color:#a6e22e\">errors<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">_runValidator<\/span>(); <span style=\"color:#75715e\">\/\/ Sync validators\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>    (<span style=\"color:#66d9ef\">this<\/span> <span style=\"color:#66d9ef\">as<\/span>{<span style=\"color:#a6e22e\">status<\/span>: <span style=\"color:#66d9ef\">string<\/span>}).<span style=\"color:#a6e22e\">status<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">_calculateStatus<\/span>(); <span style=\"color:#75715e\">\/\/ VALID | INVALID | PENDING | DISABLED\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">status<\/span> <span style=\"color:#f92672\">===<\/span> <span style=\"color:#a6e22e\">VALID<\/span> <span style=\"color:#f92672\">||<\/span> <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">status<\/span> <span style=\"color:#f92672\">===<\/span> <span style=\"color:#a6e22e\">PENDING<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">_runAsyncValidator<\/span>(<span style=\"color:#a6e22e\">opts<\/span>.<span style=\"color:#a6e22e\">emitEvent<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>    }\n<\/span><\/span><span style=\"display:flex;\"><span>  }\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#a6e22e\">opts<\/span>.<span style=\"color:#a6e22e\">emitEvent<\/span> <span style=\"color:#f92672\">!==<\/span> <span style=\"color:#66d9ef\">false<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>    (<span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">valueChanges<\/span> <span style=\"color:#66d9ef\">as<\/span> <span style=\"color:#a6e22e\">EventEmitter<\/span>&lt;<span style=\"color:#f92672\">any<\/span>&gt;).<span style=\"color:#a6e22e\">emit<\/span>(<span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">value<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>    (<span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">statusChanges<\/span> <span style=\"color:#66d9ef\">as<\/span> <span style=\"color:#a6e22e\">EventEmitter<\/span>&lt;<span style=\"color:#f92672\">string<\/span>&gt;).<span style=\"color:#a6e22e\">emit<\/span>(<span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">status<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>  }\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">_parent<\/span> <span style=\"color:#f92672\">&amp;&amp;<\/span> <span style=\"color:#f92672\">!<\/span><span style=\"color:#a6e22e\">opts<\/span>.<span style=\"color:#a6e22e\">onlySelf<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">_parent<\/span>.<span style=\"color:#a6e22e\">updateValueAndValidity<\/span>(<span style=\"color:#a6e22e\">opts<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>  }\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p>As shown above, this method is responsible for multiple things:<\/p>\n<ol>\n<li>updating the current <code>AbstractControl<\/code>&rsquo;s value<\/li>\n<li>running validators(sync &amp; async)<\/li>\n<li>calculating status based on what validators return<\/li>\n<li>emitting the new value and the new status to the subscribers(unless <code>emitEvent = false<\/code>)<\/li>\n<li>repeating 1-4 for the parent(unless <code>onlySelf = true<\/code>)<\/li>\n<\/ol>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-tsx\" data-lang=\"tsx\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">fg<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">new<\/span> <span style=\"color:#a6e22e\">FormGroup<\/span>({\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">name<\/span>: <span style=\"color:#66d9ef\">new<\/span> <span style=\"color:#a6e22e\">FormControl<\/span>(<span style=\"color:#e6db74\">&#39;&#39;<\/span>),\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">address<\/span>: <span style=\"color:#66d9ef\">new<\/span> <span style=\"color:#a6e22e\">FormGroup<\/span>({\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">city<\/span>: <span style=\"color:#66d9ef\">new<\/span> <span style=\"color:#a6e22e\">FormControl<\/span>(<span style=\"color:#e6db74\">&#39;&#39;<\/span>),\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">street<\/span>: <span style=\"color:#66d9ef\">new<\/span> <span style=\"color:#a6e22e\">FormControl<\/span>(<span style=\"color:#e6db74\">&#39;&#39;<\/span>),\n<\/span><\/span><span style=\"display:flex;\"><span>  }),\n<\/span><\/span><span style=\"display:flex;\"><span>});\n<\/span><\/span><\/code><\/pre><\/div><div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-markdown\" data-lang=\"markdown\"><span style=\"display:flex;\"><span>FG (3)\n<\/span><\/span><span style=\"display:flex;\"><span>  \/  \\\n<\/span><\/span><span style=\"display:flex;\"><span> FC  FG (2)\n<\/span><\/span><span style=\"display:flex;\"><span>    \/  \\\n<\/span><\/span><span style=\"display:flex;\"><span>   FC  FC (1)\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>(1) - fg.get(&#39;address.street&#39;)\n<\/span><\/span><span style=\"display:flex;\"><span>(2) - fg.get(&#39;address&#39;)\n<\/span><\/span><span style=\"display:flex;\"><span>(3) - fg\n<\/span><\/span><\/code><\/pre><\/div><p>As soon as you do <code>(1).setValue('new value')<\/code>, <code>(1).updateValueAndValidity()<\/code> will be invoked.<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-tsx\" data-lang=\"tsx\"><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">setValue<\/span>(<span style=\"color:#a6e22e\">value<\/span>: <span style=\"color:#66d9ef\">any<\/span>, <span style=\"color:#a6e22e\">options<\/span><span style=\"color:#f92672\">:<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">onlySelf?<\/span>: <span style=\"color:#66d9ef\">boolean<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">emitEvent?<\/span>: <span style=\"color:#66d9ef\">boolean<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">emitModelToViewChange?<\/span>: <span style=\"color:#66d9ef\">boolean<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">emitViewToModelChange?<\/span>: <span style=\"color:#66d9ef\">boolean<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>} <span style=\"color:#f92672\">=<\/span> {})<span style=\"color:#f92672\">:<\/span> <span style=\"color:#66d9ef\">void<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>  (<span style=\"color:#66d9ef\">this<\/span> <span style=\"color:#66d9ef\">as<\/span>{<span style=\"color:#a6e22e\">value<\/span>: <span style=\"color:#66d9ef\">any<\/span>}).<span style=\"color:#a6e22e\">value<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">_pendingValue<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">value<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">_onChange<\/span>.<span style=\"color:#a6e22e\">length<\/span> <span style=\"color:#f92672\">&amp;&amp;<\/span> <span style=\"color:#a6e22e\">options<\/span>.<span style=\"color:#a6e22e\">emitModelToViewChange<\/span> <span style=\"color:#f92672\">!==<\/span> <span style=\"color:#66d9ef\">false<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">_onChange<\/span>.<span style=\"color:#a6e22e\">forEach<\/span>(\n<\/span><\/span><span style=\"display:flex;\"><span>        (<span style=\"color:#a6e22e\">changeFn<\/span>) <span style=\"color:#f92672\">=&gt;<\/span> <span style=\"color:#a6e22e\">changeFn<\/span>(<span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">value<\/span>, <span style=\"color:#a6e22e\">options<\/span>.<span style=\"color:#a6e22e\">emitViewToModelChange<\/span> <span style=\"color:#f92672\">!==<\/span> <span style=\"color:#66d9ef\">false<\/span>));\n<\/span><\/span><span style=\"display:flex;\"><span>  }\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">updateValueAndValidity<\/span>(<span style=\"color:#a6e22e\">options<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p>After <code>(1)<\/code> has been updated, <code>(2)<\/code> will be updated and so on.. until the root is reached.<\/p>\n<h3 id=\"disablingenabling-abstractcontrols\">\n  <span>\n  Disabling\/enabling <code>AbstractControl<\/code>s\n  <\/span>\n  <a href=\"#disablingenabling-abstractcontrols\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h3><p>An <code>AbstractControl<\/code> can be disabled\/enabled from the <strong>model<\/strong>. The change can be seen in the view with the help of <code>ControlValueAccessor.setDisabledState<\/code>:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-tsx\" data-lang=\"tsx\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">export<\/span> <span style=\"color:#66d9ef\">function<\/span> <span style=\"color:#a6e22e\">setUpControl<\/span>(<span style=\"color:#a6e22e\">control<\/span>: <span style=\"color:#66d9ef\">FormControl<\/span>, <span style=\"color:#a6e22e\">dir<\/span>: <span style=\"color:#66d9ef\">NgControl<\/span>)<span style=\"color:#f92672\">:<\/span> <span style=\"color:#66d9ef\">void<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#75715e\">\/* ... *\/<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>  \n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#a6e22e\">dir<\/span>.<span style=\"color:#a6e22e\">valueAccessor<\/span> <span style=\"color:#f92672\">!<\/span>.<span style=\"color:#a6e22e\">setDisabledState<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">control<\/span>.<span style=\"color:#a6e22e\">registerOnDisabledChange<\/span>(\n<\/span><\/span><span style=\"display:flex;\"><span>        (<span style=\"color:#a6e22e\">isDisabled<\/span>: <span style=\"color:#66d9ef\">boolean<\/span>) <span style=\"color:#f92672\">=&gt;<\/span> { <span style=\"color:#a6e22e\">dir<\/span>.<span style=\"color:#a6e22e\">valueAccessor<\/span> <span style=\"color:#f92672\">!<\/span>.<span style=\"color:#a6e22e\">setDisabledState<\/span> <span style=\"color:#f92672\">!<\/span>(<span style=\"color:#a6e22e\">isDisabled<\/span>); });\n<\/span><\/span><span style=\"display:flex;\"><span>  }\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#75715e\">\/* ... *\/<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p>When <strong>disabling<\/strong> an <code>AbstractControl<\/code> instance you can choose not to update its ancestors by using <code>this.control.disable({ onlySelf: true })<\/code>. This might be the case when a <code>FormControl<\/code> might be part of the a <code>FormGroup<\/code> and because of this control being <strong>invalid<\/strong>, the entire <code>FormGroup<\/code> is marked as invalid.<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-tsx\" data-lang=\"tsx\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">fg<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">fb<\/span>.<span style=\"color:#a6e22e\">group<\/span>({\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">name<\/span>: <span style=\"color:#66d9ef\">this.fb.control<\/span>(<span style=\"color:#e6db74\">&#39;&#39;<\/span>, <span style=\"color:#a6e22e\">Validators<\/span>.<span style=\"color:#a6e22e\">required<\/span>),\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">age<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;&#39;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">city<\/span>: <span style=\"color:#66d9ef\">this.fb.control<\/span>(<span style=\"color:#e6db74\">&#39;&#39;<\/span>, <span style=\"color:#a6e22e\">Validators<\/span>.<span style=\"color:#a6e22e\">required<\/span>)\n<\/span><\/span><span style=\"display:flex;\"><span>});\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">fg<\/span>.<span style=\"color:#a6e22e\">controls<\/span>[<span style=\"color:#e6db74\">&#39;name&#39;<\/span>].<span style=\"color:#a6e22e\">disable<\/span>();\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">fg<\/span>.<span style=\"color:#a6e22e\">controls<\/span>[<span style=\"color:#e6db74\">&#39;city&#39;<\/span>].<span style=\"color:#a6e22e\">disable<\/span>({ <span style=\"color:#a6e22e\">onlySelf<\/span>: <span style=\"color:#66d9ef\">true<\/span> });\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">console<\/span>.<span style=\"color:#a6e22e\">log<\/span>(<span style=\"color:#a6e22e\">fg<\/span>.<span style=\"color:#a6e22e\">valid<\/span>) <span style=\"color:#75715e\">\/\/ false\n<\/span><\/span><\/span><\/code><\/pre><\/div><p>Had we omitted <code>{ onlySelf: true }<\/code>, the entire form group(<code>fg<\/code>) would&rsquo;ve been valid(<code>fg.valid === true<\/code>).<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-tsx\" data-lang=\"tsx\"><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">disable<\/span>(<span style=\"color:#a6e22e\">opts<\/span><span style=\"color:#f92672\">:<\/span> {<span style=\"color:#a6e22e\">onlySelf?<\/span>: <span style=\"color:#66d9ef\">boolean<\/span>, <span style=\"color:#a6e22e\">emitEvent?<\/span>: <span style=\"color:#66d9ef\">boolean<\/span>} <span style=\"color:#f92672\">=<\/span> {})<span style=\"color:#f92672\">:<\/span> <span style=\"color:#66d9ef\">void<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#75715e\">\/\/ If parent has been marked artificially dirty we don&#39;t want to re-calculate the\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>  <span style=\"color:#75715e\">\/\/ parent&#39;s dirtiness based on the children.\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>  <span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">skipPristineCheck<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">_parentMarkedDirty<\/span>(<span style=\"color:#a6e22e\">opts<\/span>.<span style=\"color:#a6e22e\">onlySelf<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>  (<span style=\"color:#66d9ef\">this<\/span> <span style=\"color:#66d9ef\">as<\/span>{<span style=\"color:#a6e22e\">status<\/span>: <span style=\"color:#66d9ef\">string<\/span>}).<span style=\"color:#a6e22e\">status<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">DISABLED<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>  (<span style=\"color:#66d9ef\">this<\/span> <span style=\"color:#66d9ef\">as<\/span>{<span style=\"color:#a6e22e\">errors<\/span>: <span style=\"color:#66d9ef\">ValidationErrors<\/span> <span style=\"color:#f92672\">|<\/span> <span style=\"color:#66d9ef\">null<\/span>}).<span style=\"color:#a6e22e\">errors<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">null<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">_forEachChild<\/span>(\n<\/span><\/span><span style=\"display:flex;\"><span>      (<span style=\"color:#a6e22e\">control<\/span>: <span style=\"color:#66d9ef\">AbstractControl<\/span>) <span style=\"color:#f92672\">=&gt;<\/span> { <span style=\"color:#a6e22e\">control<\/span>.<span style=\"color:#a6e22e\">disable<\/span>({...<span style=\"color:#a6e22e\">opts<\/span>, <span style=\"color:#a6e22e\">onlySelf<\/span>: <span style=\"color:#66d9ef\">true<\/span>}); });\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">_updateValue<\/span>();\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#a6e22e\">opts<\/span>.<span style=\"color:#a6e22e\">emitEvent<\/span> <span style=\"color:#f92672\">!==<\/span> <span style=\"color:#66d9ef\">false<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>    (<span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">valueChanges<\/span> <span style=\"color:#66d9ef\">as<\/span> <span style=\"color:#a6e22e\">EventEmitter<\/span>&lt;<span style=\"color:#f92672\">any<\/span>&gt;).<span style=\"color:#a6e22e\">emit<\/span>(<span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">value<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>    (<span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">statusChanges<\/span> <span style=\"color:#66d9ef\">as<\/span> <span style=\"color:#a6e22e\">EventEmitter<\/span>&lt;<span style=\"color:#f92672\">string<\/span>&gt;).<span style=\"color:#a6e22e\">emit<\/span>(<span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">status<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>  }\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#75715e\">\/\/ Will update the value, validity, dirtiness, and touch status\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>  <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">_updateAncestors<\/span>({...<span style=\"color:#a6e22e\">opts<\/span>, <span style=\"color:#a6e22e\">skipPristineCheck<\/span>});\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">_onDisabledChange<\/span>.<span style=\"color:#a6e22e\">forEach<\/span>((<span style=\"color:#a6e22e\">changeFn<\/span>) <span style=\"color:#f92672\">=&gt;<\/span> <span style=\"color:#a6e22e\">changeFn<\/span>(<span style=\"color:#66d9ef\">true<\/span>));\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">private<\/span> <span style=\"color:#a6e22e\">_updateAncestors<\/span>(\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">opts<\/span><span style=\"color:#f92672\">:<\/span> {<span style=\"color:#a6e22e\">onlySelf?<\/span>: <span style=\"color:#66d9ef\">boolean<\/span>, <span style=\"color:#a6e22e\">emitEvent?<\/span>: <span style=\"color:#66d9ef\">boolean<\/span>, <span style=\"color:#a6e22e\">skipPristineCheck?<\/span>: <span style=\"color:#66d9ef\">boolean<\/span>}) {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">_parent<\/span> <span style=\"color:#f92672\">&amp;&amp;<\/span> <span style=\"color:#f92672\">!<\/span><span style=\"color:#a6e22e\">opts<\/span>.<span style=\"color:#a6e22e\">onlySelf<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">_parent<\/span>.<span style=\"color:#a6e22e\">updateValueAndValidity<\/span>(<span style=\"color:#a6e22e\">opts<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#f92672\">!<\/span><span style=\"color:#a6e22e\">opts<\/span>.<span style=\"color:#a6e22e\">skipPristineCheck<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">_parent<\/span>.<span style=\"color:#a6e22e\">_updatePristine<\/span>();\n<\/span><\/span><span style=\"display:flex;\"><span>    }\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">_parent<\/span>.<span style=\"color:#a6e22e\">_updateTouched<\/span>();\n<\/span><\/span><span style=\"display:flex;\"><span>  }\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p>When an <code>AbstractControl<\/code> is <strong>disabled,<\/strong> its validators won&rsquo;t run and its errors will be marked as <code>null<\/code> and its children are also going to be disabled.<\/p>\n<p>If a <strong>parent<\/strong> has been marked <strong>artificially dirty<\/strong>(dirtiness is <strong>not determined<\/strong> by its children: manually doing <code>{FormGroup|FormArray}.markAsDirty()<\/code>), there is <strong>no need<\/strong> to <strong>recalculate<\/strong> the <strong>parent&rsquo;s dirtiness<\/strong> based on the children because they don&rsquo;t have any effect on the parent:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-tsx\" data-lang=\"tsx\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">form<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">fb<\/span>.<span style=\"color:#a6e22e\">group<\/span>({\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">name<\/span>: <span style=\"color:#66d9ef\">this.fb.control<\/span>({ <span style=\"color:#a6e22e\">value<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;andrei&#39;<\/span>, <span style=\"color:#a6e22e\">disabled<\/span>: <span style=\"color:#66d9ef\">false<\/span> }),\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">age<\/span>: <span style=\"color:#66d9ef\">this.fb.control<\/span>(<span style=\"color:#e6db74\">&#39;&#39;<\/span>),\n<\/span><\/span><span style=\"display:flex;\"><span>});\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">nameCtrl<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">form<\/span>.<span style=\"color:#a6e22e\">controls<\/span>[<span style=\"color:#e6db74\">&#39;name&#39;<\/span>];\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ Now, its ancestors will be marked as dirty as well\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ In this case, there is only one `FormGroup`(this.form)\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span><span style=\"color:#a6e22e\">nameCtrl<\/span>.<span style=\"color:#a6e22e\">markAsDirty<\/span>();\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">nameCtrl<\/span>.<span style=\"color:#a6e22e\">disable<\/span>();\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ Now, `this.form` will be marked as `pristine`, because \n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ the child that influenced the parent&#39;s dirtiness is disabled\n<\/span><\/span><\/span><\/code><\/pre><\/div><p>Also, if a <strong>form-control-container<\/strong>(<code>FormGroup<\/code> or <code>FormArray<\/code>) is disabled, its <code>value<\/code> will the value collected from all its descendants, regardless of their <code>disabled<\/code> value:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-tsx\" data-lang=\"tsx\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">g<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">new<\/span> <span style=\"color:#a6e22e\">FormGroup<\/span>({\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">name<\/span>: <span style=\"color:#66d9ef\">new<\/span> <span style=\"color:#a6e22e\">FormControl<\/span>(<span style=\"color:#e6db74\">&#39;name&#39;<\/span>),\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">address<\/span>: <span style=\"color:#66d9ef\">new<\/span> <span style=\"color:#a6e22e\">FormGroup<\/span>({\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">city<\/span>: <span style=\"color:#66d9ef\">new<\/span> <span style=\"color:#a6e22e\">FormControl<\/span>(<span style=\"color:#e6db74\">&#39;city&#39;<\/span>),\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">street<\/span>: <span style=\"color:#66d9ef\">new<\/span> <span style=\"color:#a6e22e\">FormControl<\/span>(<span style=\"color:#e6db74\">&#39;street&#39;<\/span>),\n<\/span><\/span><span style=\"display:flex;\"><span>  }),\n<\/span><\/span><span style=\"display:flex;\"><span>});\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">g<\/span>.<span style=\"color:#66d9ef\">get<\/span>(<span style=\"color:#e6db74\">&#39;address.city&#39;<\/span>).<span style=\"color:#a6e22e\">disable<\/span>();\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">g<\/span>.<span style=\"color:#a6e22e\">controls<\/span>[<span style=\"color:#e6db74\">&#39;name&#39;<\/span>].<span style=\"color:#a6e22e\">disable<\/span>();\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">console<\/span>.<span style=\"color:#a6e22e\">log<\/span>(<span style=\"color:#a6e22e\">g<\/span>.<span style=\"color:#a6e22e\">value<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/* \n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">{\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">  &#34;address&#34;: {\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">    &#34;street&#34;: &#34;street&#34;\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">  }\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">}\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">*\/<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">g<\/span>.<span style=\"color:#a6e22e\">disable<\/span>();\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">console<\/span>.<span style=\"color:#a6e22e\">log<\/span>(<span style=\"color:#a6e22e\">g<\/span>.<span style=\"color:#a6e22e\">value<\/span>)\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#960050;background-color:#1e0010\">\/* <\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>{\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#e6db74\">&#34;name&#34;<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#34;name&#34;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#e6db74\">&#34;address&#34;<\/span><span style=\"color:#f92672\">:<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#e6db74\">&#34;city&#34;<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#34;city&#34;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#e6db74\">&#34;address&#34;<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#34;address&#34;<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>  }\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p>The reason behind this is the way <code>AbstractControl.disable()<\/code> works. Starting from the current <code>AbstractControl<\/code> it will <strong>first disable all its descendants<\/strong>, then collect their value. For example, here is how a <code>FormArray<\/code> would accumulate the values from its descendants:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-tsx\" data-lang=\"tsx\"><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">_updateValue<\/span>()<span style=\"color:#f92672\">:<\/span> <span style=\"color:#66d9ef\">void<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>  (<span style=\"color:#66d9ef\">this<\/span> <span style=\"color:#66d9ef\">as<\/span>{<span style=\"color:#a6e22e\">value<\/span>: <span style=\"color:#66d9ef\">any<\/span>}).<span style=\"color:#a6e22e\">value<\/span> <span style=\"color:#f92672\">=<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">controls<\/span>.<span style=\"color:#a6e22e\">filter<\/span>((<span style=\"color:#a6e22e\">control<\/span>) <span style=\"color:#f92672\">=&gt;<\/span> <span style=\"color:#a6e22e\">control<\/span>.<span style=\"color:#a6e22e\">enabled<\/span> <span style=\"color:#f92672\">||<\/span> <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">disabled<\/span>)\n<\/span><\/span><span style=\"display:flex;\"><span>          .<span style=\"color:#a6e22e\">map<\/span>((<span style=\"color:#a6e22e\">control<\/span>) <span style=\"color:#f92672\">=&gt;<\/span> <span style=\"color:#a6e22e\">control<\/span>.<span style=\"color:#a6e22e\">value<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p>The <code>control.enabled || this.disabled<\/code> expression allows us to get the value, even though the child control might be disabled.<\/p>\n<p>However, if the container is <strong>not disabled<\/strong> and the child control is, its value won&rsquo;t be taken into account.<\/p>\n<p>If you still want to get the form value, <strong>including<\/strong> the <strong>disabled controls<\/strong> you can use <code>{FormGroup|FormArray}.getRawValue()<\/code>:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-tsx\" data-lang=\"tsx\"><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ FormArray.getRawValue()\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span><span style=\"color:#a6e22e\">getRawValue<\/span>()<span style=\"color:#f92672\">:<\/span> <span style=\"color:#66d9ef\">any<\/span>[] {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">controls<\/span>.<span style=\"color:#a6e22e\">map<\/span>((<span style=\"color:#a6e22e\">control<\/span>: <span style=\"color:#66d9ef\">AbstractControl<\/span>) <span style=\"color:#f92672\">=&gt;<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#a6e22e\">control<\/span> <span style=\"color:#66d9ef\">instanceof<\/span> <span style=\"color:#a6e22e\">FormControl<\/span> <span style=\"color:#f92672\">?<\/span> <span style=\"color:#a6e22e\">control<\/span>.<span style=\"color:#a6e22e\">value<\/span> <span style=\"color:#f92672\">:<\/span> (&lt;<span style=\"color:#f92672\">any<\/span>&gt;<span style=\"color:#a6e22e\">control<\/span>).<span style=\"color:#a6e22e\">getRawValue<\/span>();\n<\/span><\/span><span style=\"display:flex;\"><span>  });\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><h2 id=\"how-are-css-classes-added-depending-on-abstractcontrols-status-\">\n  <span>\n  How are CSS classes added depending on AbstractControl&rsquo;s status ?\n  <\/span>\n  <a href=\"#how-are-css-classes-added-depending-on-abstractcontrols-status-\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><p>CSS classes(<code>ng-valid<\/code>, <code>ng-pristine<\/code>, <code>ng-touched<\/code> etc) are added with the help of <code>NgControlStatus<\/code> directive, which is automatically bound to a form control element when using <code>ngModel<\/code>, <code>formControl<\/code>, <code>formControlName<\/code>.<\/p>\n<p>Additionally, <code>NgControlStatusGroup<\/code> is added to the form group(<code>&lt;form&gt;<\/code>, <code>formGroupName<\/code>, <code>formGroup<\/code>, <code>ngModelGroup<\/code>, <code>formArrayName<\/code>).<\/p>\n<p>Both <code>NgControlStatus<\/code> and <code>NgControlStatusGroup<\/code> will be updated when change detection occurs.<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-tsx\" data-lang=\"tsx\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">export<\/span> <span style=\"color:#66d9ef\">class<\/span> <span style=\"color:#a6e22e\">AbstractControlStatus<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">private<\/span> <span style=\"color:#a6e22e\">_cd<\/span>: <span style=\"color:#66d9ef\">AbstractControlDirective<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">constructor<\/span>(<span style=\"color:#a6e22e\">cd<\/span>: <span style=\"color:#66d9ef\">AbstractControlDirective<\/span>) { <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">_cd<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">cd<\/span>; }\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">get<\/span> <span style=\"color:#a6e22e\">ngClassUntouched<\/span>()<span style=\"color:#f92672\">:<\/span> <span style=\"color:#66d9ef\">boolean<\/span> { <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">_cd<\/span>.<span style=\"color:#a6e22e\">control<\/span> <span style=\"color:#f92672\">?<\/span> <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">_cd.control.untouched<\/span> : <span style=\"color:#66d9ef\">false<\/span>; }\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">get<\/span> <span style=\"color:#a6e22e\">ngClassTouched<\/span>()<span style=\"color:#f92672\">:<\/span> <span style=\"color:#66d9ef\">boolean<\/span> { <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">_cd<\/span>.<span style=\"color:#a6e22e\">control<\/span> <span style=\"color:#f92672\">?<\/span> <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">_cd.control.touched<\/span> : <span style=\"color:#66d9ef\">false<\/span>; }\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">get<\/span> <span style=\"color:#a6e22e\">ngClassPristine<\/span>()<span style=\"color:#f92672\">:<\/span> <span style=\"color:#66d9ef\">boolean<\/span> { <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">_cd<\/span>.<span style=\"color:#a6e22e\">control<\/span> <span style=\"color:#f92672\">?<\/span> <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">_cd.control.pristine<\/span> : <span style=\"color:#66d9ef\">false<\/span>; }\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">get<\/span> <span style=\"color:#a6e22e\">ngClassDirty<\/span>()<span style=\"color:#f92672\">:<\/span> <span style=\"color:#66d9ef\">boolean<\/span> { <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">_cd<\/span>.<span style=\"color:#a6e22e\">control<\/span> <span style=\"color:#f92672\">?<\/span> <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">_cd.control.dirty<\/span> : <span style=\"color:#66d9ef\">false<\/span>; }\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">get<\/span> <span style=\"color:#a6e22e\">ngClassValid<\/span>()<span style=\"color:#f92672\">:<\/span> <span style=\"color:#66d9ef\">boolean<\/span> { <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">_cd<\/span>.<span style=\"color:#a6e22e\">control<\/span> <span style=\"color:#f92672\">?<\/span> <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">_cd.control.valid<\/span> : <span style=\"color:#66d9ef\">false<\/span>; }\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">get<\/span> <span style=\"color:#a6e22e\">ngClassInvalid<\/span>()<span style=\"color:#f92672\">:<\/span> <span style=\"color:#66d9ef\">boolean<\/span> { <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">_cd<\/span>.<span style=\"color:#a6e22e\">control<\/span> <span style=\"color:#f92672\">?<\/span> <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">_cd.control.invalid<\/span> : <span style=\"color:#66d9ef\">false<\/span>; }\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">get<\/span> <span style=\"color:#a6e22e\">ngClassPending<\/span>()<span style=\"color:#f92672\">:<\/span> <span style=\"color:#66d9ef\">boolean<\/span> { <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">_cd<\/span>.<span style=\"color:#a6e22e\">control<\/span> <span style=\"color:#f92672\">?<\/span> <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">_cd.control.pending<\/span> : <span style=\"color:#66d9ef\">false<\/span>; }\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">export<\/span> <span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">ngControlStatusHost<\/span> <span style=\"color:#f92672\">=<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#e6db74\">&#39;[class.ng-untouched]&#39;<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;ngClassUntouched&#39;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#e6db74\">&#39;[class.ng-touched]&#39;<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;ngClassTouched&#39;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#e6db74\">&#39;[class.ng-pristine]&#39;<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;ngClassPristine&#39;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#e6db74\">&#39;[class.ng-dirty]&#39;<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;ngClassDirty&#39;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#e6db74\">&#39;[class.ng-valid]&#39;<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;ngClassValid&#39;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#e6db74\">&#39;[class.ng-invalid]&#39;<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;ngClassInvalid&#39;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#e6db74\">&#39;[class.ng-pending]&#39;<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;ngClassPending&#39;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>};\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">@Directive<\/span>({<span style=\"color:#a6e22e\">selector<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;[formControlName],[ngModel],[formControl]&#39;<\/span>, <span style=\"color:#a6e22e\">host<\/span>: <span style=\"color:#66d9ef\">ngControlStatusHost<\/span>})\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">export<\/span> <span style=\"color:#66d9ef\">class<\/span> <span style=\"color:#a6e22e\">NgControlStatus<\/span> <span style=\"color:#66d9ef\">extends<\/span> <span style=\"color:#a6e22e\">AbstractControlStatus<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">constructor<\/span>(<span style=\"color:#66d9ef\">@Self<\/span>() <span style=\"color:#a6e22e\">cd<\/span>: <span style=\"color:#66d9ef\">NgControl<\/span>) { <span style=\"color:#66d9ef\">super<\/span>(<span style=\"color:#a6e22e\">cd<\/span>); }\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p>With that in mind you can add your custom <strong>CSS class<\/strong> depending on form control&rsquo;s(or form-control-container&rsquo;s) validity or user interaction status by using a <strong>custom directive<\/strong>.<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-tsx\" data-lang=\"tsx\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">constructor<\/span> (<span style=\"color:#66d9ef\">private<\/span> <span style=\"color:#a6e22e\">ngControlStatus<\/span>: <span style=\"color:#66d9ef\">NgControlStatus<\/span>) { }\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">@HostBinding<\/span>(<span style=\"color:#e6db74\">&#39;[class.card__price--incorrect]&#39;<\/span>) <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">ngControlStatus<\/span>.<span style=\"color:#a6e22e\">ngClassInvalid<\/span>();\n<\/span><\/span><\/code><\/pre><\/div><blockquote>\n<p>In order for this to work, your element(or component), besides the above directive, must include one of these <strong>form-control-based<\/strong> directives: <code>[formControlName]<\/code>, <code>[ngModel]<\/code>, <code>[formControl]<\/code>.<\/p>\n<\/blockquote>\n<h2 id=\"conclusion\">\n  <span>\n  Conclusion\n  <\/span>\n  <a href=\"#conclusion\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><p>I hope this article has clarified some concepts and emphasized how powerful this package can be.<\/p>\n<p>Thanks for reading!<\/p>\n"},{"title":"Exploring the HttpClientModule in Angular","link":"https:\/\/andreigatej.dev\/blog\/exploring-the-httpclientmodule-in-angular\/","pubDate":"Mon, 30 Dec 2019 00:00:00 +0000","guid":"https:\/\/andreigatej.dev\/blog\/exploring-the-httpclientmodule-in-angular\/","description":"<p><em>This article has been published on <a href=\"https:\/\/indepth.dev\/posts\/1142\/exploring-the-httpclientmodule-in-angular\" target=\"_blank\" rel=\"noopener\">indepth.dev<\/a>.<\/em><\/p>\n<h2 id=\"introduction\">\n  <span>\n  Introduction\n  <\/span>\n  <a href=\"#introduction\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><p>In this post, we are going to understand how the <code>HttpClientModule<\/code> actually works behind the scenes and find answers to some questions that might have arisen while using this module.<\/p>\n<p>My favorite way to understand how things really work is by using the debugger while having the source code in my text editor so that I can explore and make assumptions easily.<\/p>\n<h2 id=\"installing-angular-on-your-machine\">\n  <span>\n  Installing Angular on your machine\n  <\/span>\n  <a href=\"#installing-angular-on-your-machine\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-bash\" data-lang=\"bash\"><span style=\"display:flex;\"><span>git clone -b 8.2.x --single-branch https:\/\/github.com\/angular\/angular.git\n<\/span><\/span><\/code><\/pre><\/div><h2 id=\"stackblitz\">\n  <span>\n  StackBlitz\n  <\/span>\n  <a href=\"#stackblitz\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><p>You can find a StackBlitz demo <a href=\"https:\/\/stackblitz.com\/edit\/ng-understanding-http\" target=\"_blank\" rel=\"noopener\">here<\/a>.<\/p>\n<p>We are going to use it throughout the article in order to get a better understanding of how entities are connecting with each other.<\/p>\n<h2 id=\"what-is-httpclientmodule\">\n  <span>\n  What is HttpClientModule?\n  <\/span>\n  <a href=\"#what-is-httpclientmodule\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><p>The <code>HttpClientModule<\/code> is a <strong>service module<\/strong> provided by Angular that allows us to perform <strong>HTTP requests<\/strong> and easily manipulate those requests and their responses. It is called a <strong>service module<\/strong> because it <strong>only instantiates services<\/strong> and <strong>does not export<\/strong> any components, directives or pipes.<\/p>\n<h2 id=\"lets-start-exploring\">\n  <span>\n  Let&rsquo;s start exploring\n  <\/span>\n  <a href=\"#lets-start-exploring\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><p>Once in the StackBlitz project:<\/p>\n<ul>\n<li>open the dev tools<\/li>\n<li>head over to <code>token.interceptor.ts<\/code>(CTRL + P) and put a breakpoint next to the <code>console.warn()<\/code><\/li>\n<li>refresh the <em>StackBlitz browser<\/em><\/li>\n<\/ul>\n<p>Now, you should see something like this:<\/p>\n<p><p class=\"markdown-image\">\n  <img src=\"images\/img1.png\" alt=\"Content image\"  \/>\n<\/p><\/p>\n<p>By clicking on the <em>anonymous function<\/em> from <code>client.ts<\/code>, you are now in the <code>HttpClient<\/code> class, which is the one you usually inject in your services.<\/p>\n<p>As you might have expected, this class comprises the methods for the well-known HTTP verbs.<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-typescript\" data-lang=\"typescript\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">export<\/span> <span style=\"color:#66d9ef\">class<\/span> <span style=\"color:#a6e22e\">HttpClient<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">constructor<\/span> (<span style=\"color:#66d9ef\">private<\/span> <span style=\"color:#a6e22e\">handler<\/span>: <span style=\"color:#66d9ef\">HttpHandler<\/span>) { }\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#75715e\">\/* ... Method overloads ... *\/<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">request<\/span>(<span style=\"color:#a6e22e\">first<\/span>: <span style=\"color:#66d9ef\">string<\/span> <span style=\"color:#f92672\">|<\/span> <span style=\"color:#a6e22e\">HttpRequest<\/span>&lt;<span style=\"color:#f92672\">any<\/span>&gt;, <span style=\"color:#a6e22e\">url?<\/span>: <span style=\"color:#66d9ef\">string<\/span>, <span style=\"color:#a6e22e\">options<\/span><span style=\"color:#f92672\">:<\/span> {<span style=\"color:#75715e\">\/* ... *\/<\/span>})<span style=\"color:#f92672\">:<\/span> <span style=\"color:#a6e22e\">Observable<\/span>&lt;<span style=\"color:#f92672\">any<\/span>&gt; {\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#75715e\">\/* ... *\/<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>  }\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#75715e\">\/* ... Method overloads ... *\/<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">delete<\/span>(<span style=\"color:#a6e22e\">url<\/span>: <span style=\"color:#66d9ef\">string<\/span>, <span style=\"color:#a6e22e\">options<\/span><span style=\"color:#f92672\">:<\/span> {<span style=\"color:#75715e\">\/* ... *\/<\/span>})<span style=\"color:#f92672\">:<\/span> <span style=\"color:#a6e22e\">Observable<\/span>&lt;<span style=\"color:#f92672\">any<\/span>&gt; {\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">request<\/span>&lt;<span style=\"color:#f92672\">any<\/span>&gt;(<span style=\"color:#e6db74\">&#39;DELETE&#39;<\/span>, <span style=\"color:#a6e22e\">url<\/span>, <span style=\"color:#a6e22e\">options<\/span> <span style=\"color:#66d9ef\">as<\/span> <span style=\"color:#66d9ef\">any<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>  }\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#75715e\">\/* ... Method overloads ... *\/<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">get<\/span>(<span style=\"color:#a6e22e\">url<\/span>: <span style=\"color:#66d9ef\">string<\/span>, <span style=\"color:#a6e22e\">options<\/span><span style=\"color:#f92672\">:<\/span> {<span style=\"color:#75715e\">\/* ... *\/<\/span>})<span style=\"color:#f92672\">:<\/span> <span style=\"color:#a6e22e\">Observable<\/span>&lt;<span style=\"color:#f92672\">any<\/span>&gt; {\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">request<\/span>&lt;<span style=\"color:#f92672\">any<\/span>&gt;(<span style=\"color:#e6db74\">&#39;GET&#39;<\/span>, <span style=\"color:#a6e22e\">url<\/span>, <span style=\"color:#a6e22e\">options<\/span> <span style=\"color:#66d9ef\">as<\/span> <span style=\"color:#66d9ef\">any<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>  }\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#75715e\">\/* ... Method overloads ... *\/<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">post<\/span>(<span style=\"color:#a6e22e\">url<\/span>: <span style=\"color:#66d9ef\">string<\/span>, <span style=\"color:#a6e22e\">body<\/span>: <span style=\"color:#66d9ef\">any<\/span> <span style=\"color:#f92672\">|<\/span> <span style=\"color:#66d9ef\">null<\/span>, <span style=\"color:#a6e22e\">options<\/span><span style=\"color:#f92672\">:<\/span> {<span style=\"color:#75715e\">\/* ... *\/<\/span>})<span style=\"color:#f92672\">:<\/span> <span style=\"color:#a6e22e\">Observable<\/span>&lt;<span style=\"color:#f92672\">any<\/span>&gt; {\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">request<\/span>&lt;<span style=\"color:#f92672\">any<\/span>&gt;(<span style=\"color:#e6db74\">&#39;POST&#39;<\/span>, <span style=\"color:#a6e22e\">url<\/span>, <span style=\"color:#a6e22e\">addBody<\/span>(<span style=\"color:#a6e22e\">options<\/span>, <span style=\"color:#a6e22e\">body<\/span>));\n<\/span><\/span><span style=\"display:flex;\"><span>  }\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#75715e\">\/* ... Method overloads ... *\/<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">put<\/span>(<span style=\"color:#a6e22e\">url<\/span>: <span style=\"color:#66d9ef\">string<\/span>, <span style=\"color:#a6e22e\">body<\/span>: <span style=\"color:#66d9ef\">any<\/span> <span style=\"color:#f92672\">|<\/span> <span style=\"color:#66d9ef\">null<\/span>, <span style=\"color:#a6e22e\">options<\/span><span style=\"color:#f92672\">:<\/span> {<span style=\"color:#75715e\">\/* ... *\/<\/span>})<span style=\"color:#f92672\">:<\/span> <span style=\"color:#a6e22e\">Observable<\/span>&lt;<span style=\"color:#f92672\">any<\/span>&gt; {\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">request<\/span>&lt;<span style=\"color:#f92672\">any<\/span>&gt;(<span style=\"color:#e6db74\">&#39;PUT&#39;<\/span>, <span style=\"color:#a6e22e\">url<\/span>, <span style=\"color:#a6e22e\">addBody<\/span>(<span style=\"color:#a6e22e\">options<\/span>, <span style=\"color:#a6e22e\">body<\/span>));\n<\/span><\/span><span style=\"display:flex;\"><span>  }\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p>I&rsquo;d kindly recommend switching over to your text editor and start exploring this <code>HttpClient.request<\/code> method a little.<\/p>\n<p>Continuing on, put a breakpoint on the <code>line 492<\/code> and refresh the browser. The most interesting part is just about to begin!<\/p>\n<p><p class=\"markdown-image\">\n  <img src=\"images\/httpevents.png\" alt=\"Content image\"  \/>\n<\/p><\/p>\n<p>At this point, we can&rsquo;t step into <code>this.handler.handle()<\/code> because the observable is just being built and has no subscribers yet. So, we must manually set a breakpoint inside the <code>handle<\/code> method.<\/p>\n<p>To do so, switch over to your text editor and scroll up to the <code>constructor<\/code>.<br>\nThe <code>HttpHandler<\/code> is a <strong>DI token<\/strong> that maps to <code>HttpInterceptingHandler<\/code>.<\/p>\n<p>Here&rsquo;s a list of all providers:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-typescript\" data-lang=\"typescript\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">@NgModule<\/span>({\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#75715e\">\/* ... *\/<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>  \n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">providers<\/span><span style=\"color:#f92672\">:<\/span> [\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#a6e22e\">HttpClient<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>      { <span style=\"color:#a6e22e\">provide<\/span>: <span style=\"color:#66d9ef\">HttpHandler<\/span>, <span style=\"color:#a6e22e\">useClass<\/span>: <span style=\"color:#66d9ef\">HttpInterceptingHandler<\/span> },\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#a6e22e\">HttpXhrBackend<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>      { <span style=\"color:#a6e22e\">provide<\/span>: <span style=\"color:#66d9ef\">HttpBackend<\/span>, <span style=\"color:#a6e22e\">useExisting<\/span>: <span style=\"color:#66d9ef\">HttpXhrBackend<\/span> },\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#a6e22e\">BrowserXhr<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>      { <span style=\"color:#a6e22e\">provide<\/span>: <span style=\"color:#66d9ef\">XhrFactory<\/span>, <span style=\"color:#a6e22e\">useExisting<\/span>: <span style=\"color:#66d9ef\">BrowserXhr<\/span> },\n<\/span><\/span><span style=\"display:flex;\"><span>  ],\n<\/span><\/span><span style=\"display:flex;\"><span>})\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">export<\/span> <span style=\"color:#66d9ef\">class<\/span> <span style=\"color:#a6e22e\">HttpClientModule<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p>What&rsquo;s left to do is to go into <code>HttpInterceptingHandler<\/code> class and set a breakpoint inside the <code>handle<\/code> method.<\/p>\n<p>After successufully identifying its location, switch back to your dev tools, add your breakpoint and resume the execution!<\/p>\n<p><p class=\"markdown-image\">\n  <img src=\"images\/httpintercepting.png\" alt=\"Content image\"  \/>\n<\/p><\/p>\n<p><em><code>BarInterceptor<\/code> is provided in <code>app.module<\/code><\/em><\/p>\n<p>Here we are able to grab all the interceptors by injecting the \u00a0<code>HTTP_INTERCEPTOR<\/code>(a <strong>multi-provider token<\/strong>) inside our method.<\/p>\n<p>The next step consists of creating the <strong>injectors chain<\/strong>.<br>\nBut first, let&rsquo;s have a quick look at <code>HttpInterceptorHandler<\/code>:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-typescript\" data-lang=\"typescript\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">export<\/span> <span style=\"color:#66d9ef\">class<\/span> <span style=\"color:#a6e22e\">HttpInterceptorHandler<\/span> <span style=\"color:#66d9ef\">implements<\/span> <span style=\"color:#a6e22e\">HttpHandler<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">constructor<\/span>(<span style=\"color:#66d9ef\">private<\/span> <span style=\"color:#a6e22e\">next<\/span>: <span style=\"color:#66d9ef\">HttpHandler<\/span>, <span style=\"color:#66d9ef\">private<\/span> <span style=\"color:#a6e22e\">interceptor<\/span>: <span style=\"color:#66d9ef\">HttpInterceptor<\/span>) { }\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">handle<\/span>(<span style=\"color:#a6e22e\">req<\/span>: <span style=\"color:#66d9ef\">HttpRequest<\/span>&lt;<span style=\"color:#f92672\">any<\/span>&gt;)<span style=\"color:#f92672\">:<\/span> <span style=\"color:#a6e22e\">Observable<\/span>&lt;<span style=\"color:#f92672\">HttpEvent<\/span><span style=\"color:#960050;background-color:#1e0010\">&lt;<\/span><span style=\"color:#a6e22e\">any<\/span>&gt;<span style=\"color:#f92672\">&gt;<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">interceptor<\/span>.<span style=\"color:#a6e22e\">intercept<\/span>(<span style=\"color:#a6e22e\">req<\/span>, <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">next<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>  }\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p>I like to think of this <strong>chain<\/strong> as a <strong>linked list<\/strong> that is built starting off from the <strong>tail node<\/strong>.<\/p>\n<p>In order to get a better overview of this, I&rsquo;d suggest that you keep resuming the execution until you reach <code>line 42<\/code>, while paying attention to what&rsquo;s going on in the <code>Scope<\/code> tab.<\/p>\n<p>Now, after the chain has been built, we can go through the list starting off from the <code>head node<\/code> by stepping into the <code>handle<\/code> function from <code>line 42<\/code>.<\/p>\n<p>Here&rsquo;s how this linked list could look like:<\/p>\n<p><p class=\"markdown-image\">\n  <img src=\"images\/httpinterceptors.jpg\" alt=\"Content image\"  \/>\n<\/p><\/p>\n<p>Judging by the image above, we can tell that every <code>next.handle()<\/code> <strong>returns<\/strong> an <strong>observable<\/strong>.<br>\nWhat this means is that every interceptor can add custom behavior to the returned observable. Those <strong>changes<\/strong> will <strong>propagate<\/strong> in the <strong>precedent interceptors<\/strong> in the chain.<\/p>\n<p>Before going any further, let&rsquo;s focus our attention on <code>this.backend<\/code>. Where does it come from? If you take a look at the <strong>constructor<\/strong>, you should see that is provided by <code>HttpBackend<\/code>, which maps to <code>HttpXhrBackend<\/code>(if not sure why, check what this module provides).<\/p>\n<h2 id=\"lets-explore-httpxhrbackend\">\n  <span>\n  Let&rsquo;s explore <code>HttpXhrBackend<\/code>\n  <\/span>\n  <a href=\"#lets-explore-httpxhrbackend\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><p><em>Setting some breakpoints here and there will definitely lead to a better understanding! :)<\/em><\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-typescript\" data-lang=\"typescript\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">export<\/span> <span style=\"color:#66d9ef\">class<\/span> <span style=\"color:#a6e22e\">HttpXhrBackend<\/span> <span style=\"color:#66d9ef\">implements<\/span> <span style=\"color:#a6e22e\">HttpBackend<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">constructor<\/span>(<span style=\"color:#66d9ef\">private<\/span> <span style=\"color:#a6e22e\">xhrFactory<\/span>: <span style=\"color:#66d9ef\">XhrFactory<\/span>) {}\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">handle<\/span>(<span style=\"color:#a6e22e\">req<\/span>: <span style=\"color:#66d9ef\">HttpRequest<\/span>&lt;<span style=\"color:#f92672\">any<\/span>&gt;)<span style=\"color:#f92672\">:<\/span> <span style=\"color:#a6e22e\">Observable<\/span>&lt;<span style=\"color:#f92672\">HttpEvent<\/span><span style=\"color:#960050;background-color:#1e0010\">&lt;<\/span><span style=\"color:#a6e22e\">any<\/span>&gt;<span style=\"color:#f92672\">&gt;<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#75715e\">\/\/ Everything happens on Observable subscription.\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>    <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#66d9ef\">new<\/span> <span style=\"color:#a6e22e\">Observable<\/span>((<span style=\"color:#a6e22e\">observer<\/span>: <span style=\"color:#66d9ef\">Observer<\/span>&lt;<span style=\"color:#f92672\">HttpEvent<\/span><span style=\"color:#960050;background-color:#1e0010\">&lt;<\/span><span style=\"color:#a6e22e\">any<\/span>&gt;<span style=\"color:#f92672\">&gt;<\/span>) <span style=\"color:#f92672\">=&gt;<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">xhr<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">xhrFactory<\/span>.<span style=\"color:#a6e22e\">build<\/span>();\n<\/span><\/span><span style=\"display:flex;\"><span>      \n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#75715e\">\/* ... Setting up the headers ... *\/<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#75715e\">\/* ... Setting up the response type &amp; serializing the body ... *\/<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#75715e\">\/\/ partialFromXhr extracts the HttpHeaderResponse from the current XMLHttpRequest\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>      <span style=\"color:#75715e\">\/\/ state, and memoizes it into headerResponse.\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>      <span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">partialFromXhr<\/span> <span style=\"color:#f92672\">=<\/span> ()<span style=\"color:#f92672\">:<\/span> <span style=\"color:#a6e22e\">HttpHeaderResponse<\/span> <span style=\"color:#f92672\">=&gt;<\/span> { <span style=\"color:#75715e\">\/* ... *\/<\/span> };\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#75715e\">\/\/ First up is the load event, which represents a response being fully available.\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>      <span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">onLoad<\/span> <span style=\"color:#f92672\">=<\/span> () <span style=\"color:#f92672\">=&gt;<\/span> { <span style=\"color:#75715e\">\/* ... *\/<\/span> };\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">onError<\/span> <span style=\"color:#f92672\">=<\/span> (<span style=\"color:#a6e22e\">error<\/span>: <span style=\"color:#66d9ef\">ProgressEvent<\/span>) <span style=\"color:#f92672\">=&gt;<\/span> { <span style=\"color:#75715e\">\/* ... *\/<\/span> };\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#a6e22e\">xhr<\/span>.<span style=\"color:#a6e22e\">addEventListener<\/span>(<span style=\"color:#e6db74\">&#39;load&#39;<\/span>, <span style=\"color:#a6e22e\">onLoad<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#a6e22e\">xhr<\/span>.<span style=\"color:#a6e22e\">addEventListener<\/span>(<span style=\"color:#e6db74\">&#39;error&#39;<\/span>, <span style=\"color:#a6e22e\">onError<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#75715e\">\/\/ Fire the request, and notify the event stream that it was fired.\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>      <span style=\"color:#a6e22e\">xhr<\/span>.<span style=\"color:#a6e22e\">send<\/span>(<span style=\"color:#a6e22e\">reqBody<\/span> <span style=\"color:#f92672\">!<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#a6e22e\">observer<\/span>.<span style=\"color:#a6e22e\">next<\/span>({<span style=\"color:#66d9ef\">type<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#a6e22e\">HttpEventType<\/span>.<span style=\"color:#a6e22e\">Sent<\/span>});\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#75715e\">\/\/ This is the return from the Observable function, which is the\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>      <span style=\"color:#75715e\">\/\/ request cancellation handler.\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>      <span style=\"color:#66d9ef\">return<\/span> () <span style=\"color:#f92672\">=&gt;<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#a6e22e\">xhr<\/span>.<span style=\"color:#a6e22e\">removeEventListener<\/span>(<span style=\"color:#e6db74\">&#39;error&#39;<\/span>, <span style=\"color:#a6e22e\">onError<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#a6e22e\">xhr<\/span>.<span style=\"color:#a6e22e\">removeEventListener<\/span>(<span style=\"color:#e6db74\">&#39;load&#39;<\/span>, <span style=\"color:#a6e22e\">onLoad<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#a6e22e\">xhr<\/span>.<span style=\"color:#a6e22e\">abort<\/span>();\n<\/span><\/span><span style=\"display:flex;\"><span>      };\n<\/span><\/span><span style=\"display:flex;\"><span>    });\n<\/span><\/span><span style=\"display:flex;\"><span>  }\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p>The first thing that leaps to the eye is the <code>handle()<\/code> method, which is also the last method called in the <strong>interceptor chain<\/strong> because it sits in the <strong>tail<\/strong> node. It is also responsible for <strong>dispatching<\/strong> the request to the backend.<\/p>\n<p><code>partialFromXhr<\/code> - extracts the <code>HttpHeaderResponse<\/code> from the current <code>XMLHttpRequest<\/code> and memoizes it; this object needs to be computed only once can be used in multiple places. For example, it used in the <code>onLoad<\/code> and <code>onError<\/code> events<\/p>\n<p><code>onLoad<\/code> - \u00a0the callback function <strong>triggered<\/strong> when the <strong>response<\/strong> is <strong>fully available<\/strong>; it also <strong>parses<\/strong> and <strong>validates<\/strong> the <strong>body<\/strong> of the response<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">onLoad<\/span> <span style=\"color:#f92672\">=<\/span> () <span style=\"color:#f92672\">=&gt;<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#75715e\">\/\/ Read response state from the memoized partial data.\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>  <span style=\"color:#66d9ef\">let<\/span> { <span style=\"color:#a6e22e\">headers<\/span>, <span style=\"color:#a6e22e\">status<\/span>, <span style=\"color:#a6e22e\">statusText<\/span>, <span style=\"color:#a6e22e\">url<\/span> } <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">partialFromXhr<\/span>();\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#75715e\">\/\/ The body will be read out if present.\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>  <span style=\"color:#66d9ef\">let<\/span> <span style=\"color:#a6e22e\">body<\/span>: <span style=\"color:#66d9ef\">any<\/span> <span style=\"color:#f92672\">|<\/span> <span style=\"color:#66d9ef\">null<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">null<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">let<\/span> <span style=\"color:#a6e22e\">ok<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">status<\/span> <span style=\"color:#f92672\">&gt;=<\/span> <span style=\"color:#ae81ff\">200<\/span> <span style=\"color:#f92672\">&amp;&amp;<\/span> <span style=\"color:#a6e22e\">status<\/span> <span style=\"color:#f92672\">&lt;<\/span> <span style=\"color:#ae81ff\">300<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#75715e\">\/* ... Parse body and check its validity ... *\/<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#a6e22e\">ok<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#75715e\">\/\/ A successful response is delivered on the event stream.\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>      <span style=\"color:#a6e22e\">observer<\/span>.<span style=\"color:#a6e22e\">next<\/span>(<span style=\"color:#66d9ef\">new<\/span> <span style=\"color:#a6e22e\">HttpResponse<\/span>({\n<\/span><\/span><span style=\"display:flex;\"><span>          <span style=\"color:#a6e22e\">body<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>          <span style=\"color:#a6e22e\">headers<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>          <span style=\"color:#a6e22e\">status<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>          <span style=\"color:#a6e22e\">statusText<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>          <span style=\"color:#a6e22e\">url<\/span>: <span style=\"color:#66d9ef\">url<\/span> <span style=\"color:#f92672\">||<\/span> <span style=\"color:#66d9ef\">undefined<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>      }));\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#75715e\">\/\/ The full body has been received and delivered, no further events\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>      <span style=\"color:#75715e\">\/\/ are possible. This request is complete.\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>      <span style=\"color:#a6e22e\">observer<\/span>.<span style=\"color:#a6e22e\">complete<\/span>();\n<\/span><\/span><span style=\"display:flex;\"><span>  } <span style=\"color:#66d9ef\">else<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#75715e\">\/\/ An unsuccessful request is delivered on the error channel.\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>      <span style=\"color:#a6e22e\">observer<\/span>.<span style=\"color:#a6e22e\">error<\/span>(<span style=\"color:#66d9ef\">new<\/span> <span style=\"color:#a6e22e\">HttpErrorResponse<\/span>({\n<\/span><\/span><span style=\"display:flex;\"><span>          <span style=\"color:#75715e\">\/\/ The error in this case is the response body (error from the server).\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>          <span style=\"color:#a6e22e\">error<\/span>: <span style=\"color:#66d9ef\">body<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>          <span style=\"color:#a6e22e\">headers<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>          <span style=\"color:#a6e22e\">status<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>          <span style=\"color:#a6e22e\">statusText<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>          <span style=\"color:#a6e22e\">url<\/span>: <span style=\"color:#66d9ef\">url<\/span> <span style=\"color:#f92672\">||<\/span> <span style=\"color:#66d9ef\">undefined<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>      }));\n<\/span><\/span><span style=\"display:flex;\"><span>  }\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><ul>\n<li><code>onError<\/code> - the callback function called when a <strong>network error<\/strong> occurred during the request<\/li>\n<\/ul>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">onError<\/span> <span style=\"color:#f92672\">=<\/span> (<span style=\"color:#a6e22e\">error<\/span>: <span style=\"color:#66d9ef\">ProgressEvent<\/span>) <span style=\"color:#f92672\">=&gt;<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">const<\/span> {<span style=\"color:#a6e22e\">url<\/span>} <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">partialFromXhr<\/span>();\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">res<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">new<\/span> <span style=\"color:#a6e22e\">HttpErrorResponse<\/span>({\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">error<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">status<\/span>: <span style=\"color:#66d9ef\">xhr.status<\/span> <span style=\"color:#f92672\">||<\/span> <span style=\"color:#ae81ff\">0<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">statusText<\/span>: <span style=\"color:#66d9ef\">xhr.statusText<\/span> <span style=\"color:#f92672\">||<\/span> <span style=\"color:#e6db74\">&#39;Unknown Error&#39;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">url<\/span>: <span style=\"color:#66d9ef\">url<\/span> <span style=\"color:#f92672\">||<\/span> <span style=\"color:#66d9ef\">undefined<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  });\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">observer<\/span>.<span style=\"color:#a6e22e\">error<\/span>(<span style=\"color:#a6e22e\">res<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>};\n<\/span><\/span><\/code><\/pre><\/div><p>Lastly, it is important to mention that the returned observable from <code>HttpXhrBackend.handle()<\/code> will dispatch the request when we subscribe to one of the <code>HttpClient<\/code>&rsquo;s methods(<code>get<\/code>, <code>post<\/code> etc). This means that <code>HttpXhrBackend.handle()<\/code> returns a <strong>cold observable<\/strong> which can be subscribed to by using <code>concatMap<\/code>:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">httpClient<\/span>.<span style=\"color:#66d9ef\">get<\/span>(<span style=\"color:#a6e22e\">url<\/span>).<span style=\"color:#a6e22e\">subscribe<\/span>() <span style=\"color:#f92672\">-&gt;<\/span> <span style=\"color:#66d9ef\">of<\/span>(<span style=\"color:#a6e22e\">req<\/span>).<span style=\"color:#a6e22e\">pipe<\/span>(<span style=\"color:#a6e22e\">concatMap<\/span>(<span style=\"color:#a6e22e\">req<\/span> <span style=\"color:#f92672\">=&gt;<\/span> <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">handler<\/span>.<span style=\"color:#a6e22e\">handle<\/span>))\n<\/span><\/span><\/code><\/pre><\/div><p>The callback returned from the observable<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">return<\/span> () <span style=\"color:#f92672\">=&gt;<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">xhr<\/span>.<span style=\"color:#a6e22e\">removeEventListener<\/span>(<span style=\"color:#e6db74\">&#39;error&#39;<\/span>, <span style=\"color:#a6e22e\">onError<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">xhr<\/span>.<span style=\"color:#a6e22e\">removeEventListener<\/span>(<span style=\"color:#e6db74\">&#39;load&#39;<\/span>, <span style=\"color:#a6e22e\">onLoad<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">xhr<\/span>.<span style=\"color:#a6e22e\">abort<\/span>();\n<\/span><\/span><span style=\"display:flex;\"><span>};\n<\/span><\/span><\/code><\/pre><\/div><p>will be <strong>invoked<\/strong> when the <strong>observable<\/strong> \u00a0<strong>stops emitting<\/strong> values. That is, when an <strong>error<\/strong> or a <strong>complete<\/strong> notification occurs.<\/p>\n<h3 id=\"oncomplete\">\n  <span>\n  onComplete\n  <\/span>\n  <a href=\"#oncomplete\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h3><div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">obsBE$<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">new<\/span> <span style=\"color:#a6e22e\">Observable<\/span>(<span style=\"color:#a6e22e\">obs<\/span> <span style=\"color:#f92672\">=&gt;<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">timer<\/span>(<span style=\"color:#ae81ff\">1000<\/span>)\n<\/span><\/span><span style=\"display:flex;\"><span>    .<span style=\"color:#a6e22e\">subscribe<\/span>(() <span style=\"color:#f92672\">=&gt;<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#a6e22e\">obs<\/span>.<span style=\"color:#a6e22e\">next<\/span>({ <span style=\"color:#a6e22e\">response<\/span><span style=\"color:#f92672\">:<\/span> { <span style=\"color:#a6e22e\">data<\/span><span style=\"color:#f92672\">:<\/span> [<span style=\"color:#e6db74\">&#39;foo&#39;<\/span>, <span style=\"color:#e6db74\">&#39;bar&#39;<\/span>] } });\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#75715e\">\/\/ Stop receiving values!\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>      <span style=\"color:#a6e22e\">obs<\/span>.<span style=\"color:#a6e22e\">complete<\/span>();\n<\/span><\/span><span style=\"display:flex;\"><span>    })\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">return<\/span> () <span style=\"color:#f92672\">=&gt;<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#a6e22e\">console<\/span>.<span style=\"color:#a6e22e\">warn<\/span>(<span style=\"color:#e6db74\">&#34;I&#39;ve had enough values!&#34;<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>    }\n<\/span><\/span><span style=\"display:flex;\"><span>});\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">obsBE$<\/span>.<span style=\"color:#a6e22e\">subscribe<\/span>(<span style=\"color:#a6e22e\">console<\/span>.<span style=\"color:#a6e22e\">log<\/span>)\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/* \n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">--&gt;\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">response\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">I&#39;ve had enough values!\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">*\/<\/span>\n<\/span><\/span><\/code><\/pre><\/div><h3 id=\"onerror\">\n  <span>\n  onError\n  <\/span>\n  <a href=\"#onerror\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h3><div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">be$<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">new<\/span> <span style=\"color:#a6e22e\">Observable<\/span>(<span style=\"color:#a6e22e\">o<\/span> <span style=\"color:#f92672\">=&gt;<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">o<\/span>.<span style=\"color:#a6e22e\">next<\/span>(<span style=\"color:#e6db74\">&#39;foo&#39;<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">return<\/span> () <span style=\"color:#f92672\">=&gt;<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">console<\/span>.<span style=\"color:#a6e22e\">warn<\/span>(<span style=\"color:#e6db74\">&#39;NO MORE VALUES!&#39;<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>  }\n<\/span><\/span><span style=\"display:flex;\"><span>});\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">be$<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span> .<span style=\"color:#a6e22e\">pipe<\/span>(\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">flatMap<\/span>(<span style=\"color:#a6e22e\">v<\/span> <span style=\"color:#f92672\">=&gt;<\/span> <span style=\"color:#a6e22e\">throwError<\/span>(<span style=\"color:#e6db74\">&#39;foo&#39;<\/span>)),\n<\/span><\/span><span style=\"display:flex;\"><span> )\n<\/span><\/span><span style=\"display:flex;\"><span>  .<span style=\"color:#a6e22e\">subscribe<\/span>(<span style=\"color:#66d9ef\">null<\/span>, <span style=\"color:#a6e22e\">console<\/span>.<span style=\"color:#a6e22e\">error<\/span>)\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/* \n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">--&gt;\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">foo\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">NO MORE VALUES\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">*\/<\/span>\n<\/span><\/span><\/code><\/pre><\/div><h2 id=\"how-can-a-request-be-canceled\">\n  <span>\n  How can a request be canceled?\n  <\/span>\n  <a href=\"#how-can-a-request-be-canceled\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><p>A common case is the <strong>typeahead<\/strong> feature:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">keyPressed<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>  .<span style=\"color:#a6e22e\">pipe<\/span>(\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#a6e22e\">debounceTime<\/span>(<span style=\"color:#ae81ff\">300<\/span>),\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#a6e22e\">switchMap<\/span>(<span style=\"color:#a6e22e\">v<\/span> <span style=\"color:#f92672\">=&gt;<\/span> <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">http<\/span>.<span style=\"color:#66d9ef\">get<\/span>(<span style=\"color:#a6e22e\">url<\/span> <span style=\"color:#f92672\">+<\/span> <span style=\"color:#e6db74\">&#39;?key=&#39;<\/span> <span style=\"color:#f92672\">+<\/span> <span style=\"color:#a6e22e\">v<\/span>))\n<\/span><\/span><span style=\"display:flex;\"><span>  )\n<\/span><\/span><\/code><\/pre><\/div><p>It is advised to do things this way. The reason is due to <code>switchMap<\/code>&rsquo;s magic, which will <strong>unsubscribe<\/strong> from the <strong>inner observable<\/strong> to handle the next emitted value.<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">src<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">new<\/span> <span style=\"color:#a6e22e\">Observable<\/span>(<span style=\"color:#a6e22e\">obs<\/span> <span style=\"color:#f92672\">=&gt;<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">obs<\/span>.<span style=\"color:#a6e22e\">next<\/span>(<span style=\"color:#e6db74\">&#39;src 1&#39;<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">obs<\/span>.<span style=\"color:#a6e22e\">next<\/span>(<span style=\"color:#e6db74\">&#39;src 2&#39;<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>  \n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">setTimeout<\/span>(() <span style=\"color:#f92672\">=&gt;<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">obs<\/span>.<span style=\"color:#a6e22e\">next<\/span>(<span style=\"color:#e6db74\">&#39;src 3&#39;<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">obs<\/span>.<span style=\"color:#a6e22e\">complete<\/span>(); \n<\/span><\/span><span style=\"display:flex;\"><span>  }, <span style=\"color:#ae81ff\">1000<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">return<\/span> () <span style=\"color:#f92672\">=&gt;<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">console<\/span>.<span style=\"color:#a6e22e\">log<\/span>(<span style=\"color:#e6db74\">&#39;called on unsubscription&#39;<\/span>)\n<\/span><\/span><span style=\"display:flex;\"><span>  };\n<\/span><\/span><span style=\"display:flex;\"><span>});\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">of<\/span>(<span style=\"color:#ae81ff\">1<\/span>, <span style=\"color:#ae81ff\">2<\/span>)\n<\/span><\/span><span style=\"display:flex;\"><span>  .<span style=\"color:#a6e22e\">pipe<\/span>(\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">switchMap<\/span>(() <span style=\"color:#f92672\">=&gt;<\/span> <span style=\"color:#a6e22e\">src<\/span>)\n<\/span><\/span><span style=\"display:flex;\"><span>  )\n<\/span><\/span><span style=\"display:flex;\"><span>  .<span style=\"color:#a6e22e\">subscribe<\/span>(<span style=\"color:#a6e22e\">console<\/span>.<span style=\"color:#a6e22e\">log<\/span>)\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/* \n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">src 1\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">src 2\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">called on unsubscription ---&gt; unsubscribed from because the next value(`2`) kicked in\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">src 1\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">src 2\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">src 3\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">called on unsubscription ---&gt; completion\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">*\/<\/span>\n<\/span><\/span><\/code><\/pre><\/div><p><code>1<\/code> is emitted and while we are <strong>waiting<\/strong> for the <strong>inner observable<\/strong> to complete, another value, <code>2<\/code>, comes straight away and will make <code>switchMap<\/code> unsubscribe from the current inner observable which in turn will invoke the returned function from the observable.<\/p>\n<p>Here is what is going on inside the function returned from the observable that dispatches the request(found in <code>HttpXhrBackend.handle<\/code>):<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">return<\/span> () <span style=\"color:#f92672\">=&gt;<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#75715e\">\/* Skipped some lines for brevity... *\/<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">xhr<\/span>.<span style=\"color:#a6e22e\">removeEventListener<\/span>(<span style=\"color:#e6db74\">&#39;error&#39;<\/span>, <span style=\"color:#a6e22e\">onError<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">xhr<\/span>.<span style=\"color:#a6e22e\">removeEventListener<\/span>(<span style=\"color:#e6db74\">&#39;load&#39;<\/span>, <span style=\"color:#a6e22e\">onLoad<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>  \n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#75715e\">\/\/ Finally, abort the in-flight request.\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>  <span style=\"color:#a6e22e\">xhr<\/span>.<span style=\"color:#a6e22e\">abort<\/span>();\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p>Thus, we can infer that if the observable that made the request is unsubscribed from, the above callback will be invoked.<\/p>\n<h2 id=\"how-can-interceptors-retry-requests\">\n  <span>\n  How can interceptors retry requests?\n  <\/span>\n  <a href=\"#how-can-interceptors-retry-requests\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><p>A token interceptor might look like this:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">intercept<\/span> (<span style=\"color:#a6e22e\">req<\/span>: <span style=\"color:#66d9ef\">HttpRequest<\/span>&lt;<span style=\"color:#f92672\">any<\/span>&gt;, <span style=\"color:#a6e22e\">next<\/span>: <span style=\"color:#66d9ef\">HttpHandler<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#75715e\">\/* ... Attach token and all that good stuff ... *\/<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#a6e22e\">next<\/span>.<span style=\"color:#a6e22e\">handle<\/span>()\n<\/span><\/span><span style=\"display:flex;\"><span>    .<span style=\"color:#a6e22e\">pipe<\/span>(\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#a6e22e\">catchError<\/span>(<span style=\"color:#a6e22e\">err<\/span> <span style=\"color:#f92672\">=&gt;<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#a6e22e\">err<\/span> <span style=\"color:#66d9ef\">instanceof<\/span> <span style=\"color:#a6e22e\">HttpErrorResponse<\/span> <span style=\"color:#f92672\">&amp;&amp;<\/span> <span style=\"color:#a6e22e\">err<\/span>.<span style=\"color:#a6e22e\">status<\/span> <span style=\"color:#f92672\">===<\/span> <span style=\"color:#ae81ff\">401<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>          <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">handle401Error<\/span>(<span style=\"color:#a6e22e\">req<\/span>, <span style=\"color:#a6e22e\">next<\/span>)\n<\/span><\/span><span style=\"display:flex;\"><span>        }\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#75715e\">\/\/ Simply propagate the error to other interceptors or to the consumer\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>        <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#a6e22e\">throwError<\/span>(<span style=\"color:#a6e22e\">err<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>      })\n<\/span><\/span><span style=\"display:flex;\"><span>    )\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">private<\/span> <span style=\"color:#a6e22e\">handle401Error<\/span> (<span style=\"color:#a6e22e\">req<\/span>: <span style=\"color:#66d9ef\">HttpRequest<\/span>&lt;<span style=\"color:#f92672\">any<\/span>&gt;, <span style=\"color:#a6e22e\">next<\/span>: <span style=\"color:#66d9ef\">HttpHandler<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">authService<\/span>.<span style=\"color:#a6e22e\">refreshToken<\/span>()\n<\/span><\/span><span style=\"display:flex;\"><span>    .<span style=\"color:#a6e22e\">pipe<\/span>(\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#a6e22e\">tap<\/span>(<span style=\"color:#a6e22e\">token<\/span> <span style=\"color:#f92672\">=&gt;<\/span> <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">authService<\/span>.<span style=\"color:#a6e22e\">setToken<\/span>(<span style=\"color:#a6e22e\">token<\/span>)),\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#a6e22e\">map<\/span>(<span style=\"color:#a6e22e\">token<\/span> <span style=\"color:#f92672\">=&gt;<\/span> <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">attachToken<\/span>(<span style=\"color:#a6e22e\">req<\/span>, <span style=\"color:#a6e22e\">token<\/span>))\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#a6e22e\">switchMap<\/span>(<span style=\"color:#a6e22e\">req<\/span> <span style=\"color:#f92672\">=&gt;<\/span> <span style=\"color:#a6e22e\">next<\/span>.<span style=\"color:#a6e22e\">handle<\/span>(<span style=\"color:#a6e22e\">req<\/span>))\n<\/span><\/span><span style=\"display:flex;\"><span>    )\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">private<\/span> <span style=\"color:#a6e22e\">attachToken<\/span>(<span style=\"color:#a6e22e\">req<\/span>: <span style=\"color:#66d9ef\">HttpRequest<\/span>&lt;<span style=\"color:#f92672\">any<\/span>&gt;, <span style=\"color:#a6e22e\">token<\/span>: <span style=\"color:#66d9ef\">string<\/span>)<span style=\"color:#f92672\">:<\/span> <span style=\"color:#a6e22e\">HttpRequest<\/span>&lt;<span style=\"color:#f92672\">any<\/span>&gt; {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#a6e22e\">req<\/span>.<span style=\"color:#a6e22e\">clone<\/span>({ <span style=\"color:#a6e22e\">setHeaders<\/span><span style=\"color:#f92672\">:<\/span> { <span style=\"color:#e6db74\">&#39;x-access-token&#39;<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#a6e22e\">token<\/span> } })\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p>The retry logic can be achieved with <code>switchMap(() =&gt; next.handle(req))<\/code>.<\/p>\n<p>If we reach the code inside <code>catchError<\/code>, it means that the <strong>consumer<\/strong> will <strong>unsubscribe<\/strong> from the <strong>observable<\/strong>(the one that is returned from HttpXhrBackend.handle).<br>\nThis will allow us to <strong>re-subscribe<\/strong> to that observable, which will cause the request to be sent again as well as the interceptors that follow this interceptor to run their <code>intercept<\/code> function again.<\/p>\n<p>Let&rsquo;s narrow it down to a simpler example:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">obsBE$<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">new<\/span> <span style=\"color:#a6e22e\">Observable<\/span>(<span style=\"color:#a6e22e\">obs<\/span> <span style=\"color:#f92672\">=&gt;<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">timer<\/span>(<span style=\"color:#ae81ff\">1000<\/span>)\n<\/span><\/span><span style=\"display:flex;\"><span>    .<span style=\"color:#a6e22e\">subscribe<\/span>(() <span style=\"color:#f92672\">=&gt;<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#75715e\">\/\/ console.log(&#39;%c [OBSERVABLE]&#39;, &#39;color: red;&#39;);\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#a6e22e\">obs<\/span>.<span style=\"color:#a6e22e\">next<\/span>({ <span style=\"color:#a6e22e\">response<\/span><span style=\"color:#f92672\">:<\/span> { <span style=\"color:#a6e22e\">data<\/span><span style=\"color:#f92672\">:<\/span> [<span style=\"color:#e6db74\">&#39;foo&#39;<\/span>, <span style=\"color:#e6db74\">&#39;bar&#39;<\/span>] } });\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#75715e\">\/\/ Stop receiving values!\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>      <span style=\"color:#a6e22e\">obs<\/span>.<span style=\"color:#a6e22e\">complete<\/span>();\n<\/span><\/span><span style=\"display:flex;\"><span>    })\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">return<\/span> () <span style=\"color:#f92672\">=&gt;<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#a6e22e\">console<\/span>.<span style=\"color:#a6e22e\">warn<\/span>(<span style=\"color:#e6db74\">&#34;I&#39;ve had enough values!&#34;<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>    }\n<\/span><\/span><span style=\"display:flex;\"><span>});\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ Composing interceptors the chain\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span><span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">obsI1$<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">obsBE$<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>  .<span style=\"color:#a6e22e\">pipe<\/span>(\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">tap<\/span>(() <span style=\"color:#f92672\">=&gt;<\/span> <span style=\"color:#a6e22e\">console<\/span>.<span style=\"color:#a6e22e\">log<\/span>(<span style=\"color:#e6db74\">&#39;%c [i1]&#39;<\/span>, <span style=\"color:#e6db74\">&#39;color: blue;&#39;<\/span>)),\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">map<\/span>(<span style=\"color:#a6e22e\">r<\/span> <span style=\"color:#f92672\">=&gt;<\/span> ({ ...<span style=\"color:#a6e22e\">r<\/span>, <span style=\"color:#a6e22e\">i1<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;intercepted by i1!&#39;<\/span> }))\n<\/span><\/span><span style=\"display:flex;\"><span>  );\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">let<\/span> <span style=\"color:#a6e22e\">retryCnt<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#ae81ff\">0<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">obsI2$<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">obsI1$<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>  .<span style=\"color:#a6e22e\">pipe<\/span>(\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">tap<\/span>(() <span style=\"color:#f92672\">=&gt;<\/span> <span style=\"color:#a6e22e\">console<\/span>.<span style=\"color:#a6e22e\">log<\/span>(<span style=\"color:#e6db74\">&#39;%c [i2]&#39;<\/span>, <span style=\"color:#e6db74\">&#39;color: green;&#39;<\/span>)),\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">map<\/span>(<span style=\"color:#a6e22e\">r<\/span> <span style=\"color:#f92672\">=&gt;<\/span> { \n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#f92672\">++<\/span><span style=\"color:#a6e22e\">retryCnt<\/span> <span style=\"color:#f92672\">&lt;=<\/span><span style=\"color:#ae81ff\">3<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#66d9ef\">throw<\/span> <span style=\"color:#66d9ef\">new<\/span> Error(<span style=\"color:#e6db74\">&#39;err!&#39;<\/span>) \n<\/span><\/span><span style=\"display:flex;\"><span>      }\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#a6e22e\">r<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>    }),\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">catchError<\/span>((<span style=\"color:#a6e22e\">err<\/span>, <span style=\"color:#a6e22e\">caught<\/span>) <span style=\"color:#f92672\">=&gt;<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#a6e22e\">getRefreshToken<\/span>()\n<\/span><\/span><span style=\"display:flex;\"><span>        .<span style=\"color:#a6e22e\">pipe<\/span>(\n<\/span><\/span><span style=\"display:flex;\"><span>          <span style=\"color:#a6e22e\">switchMap<\/span>(() <span style=\"color:#f92672\">=&gt;<\/span> <span style=\"color:#75715e\">\/* obsI2$ *\/<\/span><span style=\"color:#a6e22e\">caught<\/span>),\n<\/span><\/span><span style=\"display:flex;\"><span>        )\n<\/span><\/span><span style=\"display:flex;\"><span>    })\n<\/span><\/span><span style=\"display:flex;\"><span>  );\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">obsI3$<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">obsI2$<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>  .<span style=\"color:#a6e22e\">pipe<\/span>(\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">tap<\/span>(() <span style=\"color:#f92672\">=&gt;<\/span> <span style=\"color:#a6e22e\">console<\/span>.<span style=\"color:#a6e22e\">log<\/span>(<span style=\"color:#e6db74\">&#39;%c [i3]&#39;<\/span>, <span style=\"color:#e6db74\">&#39;color: orange;&#39;<\/span>)),\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">map<\/span>(<span style=\"color:#a6e22e\">r<\/span> <span style=\"color:#f92672\">=&gt;<\/span> ({ ...<span style=\"color:#a6e22e\">r<\/span>, <span style=\"color:#a6e22e\">i3<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;intercepted by i3!&#39;<\/span> }))\n<\/span><\/span><span style=\"display:flex;\"><span>  );\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">function<\/span> <span style=\"color:#a6e22e\">getRefreshToken<\/span> () {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#a6e22e\">timer<\/span>(<span style=\"color:#ae81ff\">1500<\/span>)\n<\/span><\/span><span style=\"display:flex;\"><span>    .<span style=\"color:#a6e22e\">pipe<\/span>(<span style=\"color:#a6e22e\">q<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#a6e22e\">map<\/span>(() <span style=\"color:#f92672\">=&gt;<\/span> ({ <span style=\"color:#a6e22e\">token<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;TOKEN HERE&#39;<\/span> })),\n<\/span><\/span><span style=\"display:flex;\"><span>    );\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">function<\/span> <span style=\"color:#66d9ef\">get<\/span> () {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#a6e22e\">obsI3$<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">get<\/span>()\n<\/span><\/span><span style=\"display:flex;\"><span>  .<span style=\"color:#a6e22e\">subscribe<\/span>(<span style=\"color:#a6e22e\">console<\/span>.<span style=\"color:#a6e22e\">log<\/span>)\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/* \n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">--&gt;\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">[i1]\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">[i2]\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">I&#39;ve had enough values!\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">[i1]\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">[i2]\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">I&#39;ve had enough values!\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">[i1]\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">[i2]\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">I&#39;ve had enough values!\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">[i1]\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">[i2]\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">[i3]\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">{\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">  &#34;response&#34;: {\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">    &#34;data&#34;: [\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">      &#34;foo&#34;,\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">      &#34;bar&#34;\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">    ]\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">  },\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">  &#34;i1&#34;: &#34;intercepted by i1!&#34;,\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">  &#34;i3&#34;: &#34;intercepted by i3!&#34;\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">}\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">I&#39;ve had enough values!\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">*\/<\/span>\n<\/span><\/span><\/code><\/pre><\/div><p><em><a href=\"https:\/\/stackblitz.com\/edit\/rx-playground-3locfw\" target=\"_blank\" rel=\"noopener\">StackBlitz.<\/a><\/em><\/p>\n<p>This is, in my view, the effect of <code>next.handle()<\/code> inside each interceptor(Image here). Imagine that instead of <code>const obsI3$ = obsI2$<\/code> we would have something like this:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ Interceptor Nr.2\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span><span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">next<\/span> <span style=\"color:#f92672\">=<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">handle<\/span>(<span style=\"color:#a6e22e\">req<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#75715e\">\/* ... Some logic here ... *\/<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#66d9ef\">of<\/span>({ <span style=\"color:#a6e22e\">response<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;&#39;<\/span> })\n<\/span><\/span><span style=\"display:flex;\"><span>  }\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">obsI3$<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">next<\/span>.<span style=\"color:#a6e22e\">handle<\/span>(<span style=\"color:#a6e22e\">req<\/span>)\n<\/span><\/span><span style=\"display:flex;\"><span>  .<span style=\"color:#a6e22e\">pipe<\/span>(\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">map<\/span>(<span style=\"color:#a6e22e\">r<\/span> <span style=\"color:#f92672\">=&gt;<\/span> ({ ...<span style=\"color:#a6e22e\">r<\/span>, <span style=\"color:#a6e22e\">i3<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;this is interceptor 3!!&#39;<\/span> })),\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#75715e\">\/* ... *\/<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>  )\n<\/span><\/span><\/code><\/pre><\/div><p><code>obsI3$<\/code> will now be the observable returned by <code>next.handle()<\/code> which means it can add now its own custom behavior and if something goes wrong, it can reinvoke the source observable.<\/p>\n<p>When using interceptors you would want to retry the request by using <code>switchMap(() =&gt; next.handle(req)<\/code>(as it is done in the first code snippet), because, besides the each interceptor&rsquo;s returned observable, you would also want to run their logic that sits inside their <code>intercept()<\/code> function.<\/p>\n<p>From this line <code>switchMap(() =&gt; \/* obsI2$ *\/caught)<\/code> we can see that <code>catchError<\/code> can have a second argument, <code>caught<\/code>, which is the source observable.(More on this <a href=\"https:\/\/github.com\/ReactiveX\/rxjs\/blob\/master\/src\/internal\/operators\/catchError.ts#L99-L106\" target=\"_blank\" rel=\"noopener\">here<\/a>)<\/p>\n<h2 id=\"why-is-it-sometimes-necessary-to-clone-the-request-object-inside-an-interceptor\">\n  <span>\n  Why is it sometimes necessary to clone the request object inside an interceptor?\n  <\/span>\n  <a href=\"#why-is-it-sometimes-necessary-to-clone-the-request-object-inside-an-interceptor\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><p>The process of adding the JWT token to your request might look like this:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#a6e22e\">token<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">request<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">request<\/span>.<span style=\"color:#a6e22e\">clone<\/span>({\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">setHeaders<\/span><span style=\"color:#f92672\">:<\/span> { [<span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">AuthHeader<\/span>]<span style=\"color:#f92672\">:<\/span> <span style=\"color:#a6e22e\">token<\/span> },\n<\/span><\/span><span style=\"display:flex;\"><span>  });\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#a6e22e\">next<\/span>.<span style=\"color:#a6e22e\">handle<\/span>(<span style=\"color:#a6e22e\">request<\/span>)\n<\/span><\/span><\/code><\/pre><\/div><p>The most important reason would be <strong>immutability<\/strong>. You wouldn&rsquo;t want to mutate the <strong>request object<\/strong> from multiple places. Thus, every interceptor should configure the request independently.<br>\nThe cloned request would eventually be passed to the next interceptor in the chain.<\/p>\n<h2 id=\"why-is-it-recommended-to-load-the-httpclientmodule-only-once-in-appmodule-or-coremodule\">\n  <span>\n  Why is it recommended to load the HttpClientModule only once in AppModule or CoreModule?\n  <\/span>\n  <a href=\"#why-is-it-recommended-to-load-the-httpclientmodule-only-once-in-appmodule-or-coremodule\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><p>A lazy-loaded module <code>A<\/code> will create its own child injector which will resolve the <code>providers<\/code> from that module. This means that the <strong>providers provided inside<\/strong> <code>A<\/code> and those <strong>provided by modules imported by<\/strong> <code>A<\/code> will be <strong>scoped<\/strong> to module <code>A<\/code>.<\/p>\n<p>Importing <code>HttpClientModule<\/code> in <code>A<\/code> will result in only <strong>applying<\/strong> the <strong>interceptors<\/strong> that are <strong>provided<\/strong> inside <strong><code>A<\/code><\/strong>, excluding anything that is up in the injector tree. This is because <code>HttpClientModule<\/code> comes with its <strong>own providers<\/strong> which, as mentioned above, will be scoped to <code>A<\/code>.<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-markdown\" data-lang=\"markdown\"><span style=\"display:flex;\"><span>  { provide: HttpHandler, useClass: ... }\n<\/span><\/span><span style=\"display:flex;\"><span>  AppModule {    \/\n<\/span><\/span><span style=\"display:flex;\"><span>    imports: [  \/\n<\/span><\/span><span style=\"display:flex;\"><span>      HttpClientModule\n<\/span><\/span><span style=\"display:flex;\"><span>    ]\n<\/span><\/span><span style=\"display:flex;\"><span>  }\n<\/span><\/span><span style=\"display:flex;\"><span>                  { provide: HttpHandler, useClass: HttpInterceptingHandler } &lt;<span style=\"color:#f92672\">-<\/span> <span style=\"color:#a6e22e\">where<\/span> <span style=\"color:#a6e22e\">interceptors<\/span> <span style=\"color:#a6e22e\">are<\/span> <span style=\"color:#a6e22e\">gathered<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">FeatureModule<\/span> <span style=\"color:#960050;background-color:#1e0010\">{<\/span> <span style=\"color:#960050;background-color:#1e0010\">\/<\/span>  <span style=\"color:#960050;background-color:#1e0010\">&lt;<\/span><span style=\"color:#a6e22e\">-<\/span> <span style=\"color:#a6e22e\">lazy-loaded<\/span>                  <span style=\"color:#960050;background-color:#1e0010\">|<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">imports:<\/span> <span style=\"color:#960050;background-color:#1e0010\">[<\/span>   <span style=\"color:#960050;background-color:#1e0010\">\/<\/span>                                   <span style=\"color:#960050;background-color:#1e0010\">|<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#a6e22e\">HttpClientModule<\/span> <span style=\"color:#960050;background-color:#1e0010\">&lt;<\/span><span style=\"color:#a6e22e\">------------------<\/span>           <span style=\"color:#960050;background-color:#1e0010\">|<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#960050;background-color:#1e0010\">]<\/span>                                     <span style=\"color:#960050;background-color:#1e0010\">|<\/span>          <span style=\"color:#960050;background-color:#1e0010\">|<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>                                          <span style=\"color:#960050;background-color:#1e0010\">|<\/span>          <span style=\"color:#960050;background-color:#1e0010\">|<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">declarations:<\/span> <span style=\"color:#960050;background-color:#1e0010\">[<\/span><span style=\"color:#a6e22e\">FeatureComponent<\/span><span style=\"color:#960050;background-color:#1e0010\">]<\/span>       <span style=\"color:#960050;background-color:#1e0010\">&lt;<\/span><span style=\"color:#a6e22e\">------------------------<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">providers:<\/span> <span style=\"color:#960050;background-color:#1e0010\">[<\/span>                                     <span style=\"color:#960050;background-color:#1e0010\">|<\/span>              <span style=\"color:#960050;background-color:#1e0010\">|<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>                                                    <span style=\"color:#960050;background-color:#1e0010\">\/<\/span>               <span style=\"color:#960050;background-color:#1e0010\">|<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#960050;background-color:#1e0010\">{<\/span> <span style=\"color:#a6e22e\">provide:<\/span> <span style=\"color:#a6e22e\">HTTP_INTERCEPTORS<\/span><span style=\"color:#960050;background-color:#1e0010\">,<\/span> <span style=\"color:#a6e22e\">useClass:<\/span> <span style=\"color:#a6e22e\">FeatInterceptor_1<\/span> <span style=\"color:#960050;background-color:#1e0010\">},<\/span>  <span style=\"color:#960050;background-color:#1e0010\">|<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#960050;background-color:#1e0010\">{<\/span> <span style=\"color:#a6e22e\">provide:<\/span> <span style=\"color:#a6e22e\">HTTP_INTERCEPTORS<\/span><span style=\"color:#960050;background-color:#1e0010\">,<\/span> <span style=\"color:#a6e22e\">useClass:<\/span> <span style=\"color:#a6e22e\">FeatInterceptor_2<\/span> <span style=\"color:#960050;background-color:#1e0010\">}<\/span>   <span style=\"color:#960050;background-color:#1e0010\">|<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#960050;background-color:#1e0010\">]<\/span>                                      <span style=\"color:#a6e22e\">------------------------<\/span>&gt;\n<\/span><\/span><span style=\"display:flex;\"><span>  }                                       |\n<\/span><\/span><span style=\"display:flex;\"><span>                                          | httpClient.get()\n<\/span><\/span><span style=\"display:flex;\"><span>  FeatureComponent {                      |\n<\/span><\/span><span style=\"display:flex;\"><span>    constructor (private httpClient: HttpClient) { }\n<\/span><\/span><span style=\"display:flex;\"><span>  }\n<\/span><\/span><\/code><\/pre><\/div><p>If <code>HttpClientModule<\/code> was <strong>not imported<\/strong> in <code>A<\/code>, it would <strong>look up<\/strong> the <strong>injector tree<\/strong> until it finds the needed providers(in this case, it would be in <code>AppModule<\/code>). This also means that any interceptors provided in <code>A<\/code> will be <strong>excluded<\/strong>.<\/p>\n<h2 id=\"how-can-interceptors-be-completely-bypassed\">\n  <span>\n  How can interceptors be completely bypassed?\n  <\/span>\n  <a href=\"#how-can-interceptors-be-completely-bypassed\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><h3 id=\"tldr\">\n  <span>\n  TLDR;\n  <\/span>\n  <a href=\"#tldr\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h3><p>Make sure that <code>HttpHandler<\/code> maps to <code>HttpXhrBackend<\/code>:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">@NgModule<\/span>({\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">imports<\/span><span style=\"color:#f92672\">:<\/span> [\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#75715e\">\/* ... *\/<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">HttpClientModule<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#75715e\">\/* ... *\/<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>  ],\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">declarations<\/span><span style=\"color:#f92672\">:<\/span> [ <span style=\"color:#75715e\">\/* ... *\/<\/span> ],\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">providers<\/span><span style=\"color:#f92672\">:<\/span> [\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#75715e\">\/* ... *\/<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>    {\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#a6e22e\">provide<\/span>: <span style=\"color:#66d9ef\">HttpHandler<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#a6e22e\">useExisting<\/span>: <span style=\"color:#66d9ef\">HttpXhrBackend<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>    },\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#75715e\">\/* ... *\/<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>  ]\n<\/span><\/span><span style=\"display:flex;\"><span>})\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">export<\/span> <span style=\"color:#66d9ef\">class<\/span> <span style=\"color:#a6e22e\">AppModule<\/span> { }\n<\/span><\/span><\/code><\/pre><\/div><h3 id=\"detailed-explanation\">\n  <span>\n  Detailed Explanation\n  <\/span>\n  <a href=\"#detailed-explanation\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h3><p>Whenever you do something like <code>HttpClient.get()<\/code>(or any other <strong>HTTP verb<\/strong>), the <code>HttpClient.request()<\/code> method will be eventually called. In this method, this line will be reached:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">events$<\/span>: <span style=\"color:#66d9ef\">Observable<\/span>&lt;<span style=\"color:#f92672\">HttpEvent<\/span><span style=\"color:#960050;background-color:#1e0010\">&lt;<\/span><span style=\"color:#a6e22e\">any<\/span>&gt;<span style=\"color:#f92672\">&gt;<\/span> <span style=\"color:#f92672\">=<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#66d9ef\">of<\/span>(<span style=\"color:#a6e22e\">req<\/span>).<span style=\"color:#a6e22e\">pipe<\/span>(<span style=\"color:#a6e22e\">concatMap<\/span>((<span style=\"color:#a6e22e\">req<\/span>: <span style=\"color:#66d9ef\">HttpRequest<\/span>&lt;<span style=\"color:#f92672\">any<\/span>&gt;) <span style=\"color:#f92672\">=&gt;<\/span> <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">handler<\/span>.<span style=\"color:#a6e22e\">handle<\/span>(<span style=\"color:#a6e22e\">req<\/span>)));\n<\/span><\/span><\/code><\/pre><\/div><p>Let&rsquo;s see how <code>this.handler<\/code> is retrieved:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">@Injectable<\/span>()\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">export<\/span> <span style=\"color:#66d9ef\">class<\/span> <span style=\"color:#a6e22e\">HttpClient<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">constructor<\/span>(<span style=\"color:#66d9ef\">private<\/span> <span style=\"color:#a6e22e\">handler<\/span>: <span style=\"color:#66d9ef\">HttpHandler<\/span>) {}\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#75715e\">\/* ... *\/<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p>If we take a look at <code>HttpClientModule<\/code>&rsquo;s providers,<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">@NgModule<\/span>({\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#75715e\">\/* ... *\/<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>  \n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">providers<\/span><span style=\"color:#f92672\">:<\/span> [\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#a6e22e\">HttpClient<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>      { <span style=\"color:#a6e22e\">provide<\/span>: <span style=\"color:#66d9ef\">HttpHandler<\/span>, <span style=\"color:#a6e22e\">useClass<\/span>: <span style=\"color:#66d9ef\">HttpInterceptingHandler<\/span> },\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#a6e22e\">HttpXhrBackend<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>      { <span style=\"color:#a6e22e\">provide<\/span>: <span style=\"color:#66d9ef\">HttpBackend<\/span>, <span style=\"color:#a6e22e\">useExisting<\/span>: <span style=\"color:#66d9ef\">HttpXhrBackend<\/span> },\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#a6e22e\">BrowserXhr<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>      { <span style=\"color:#a6e22e\">provide<\/span>: <span style=\"color:#66d9ef\">XhrFactory<\/span>, <span style=\"color:#a6e22e\">useExisting<\/span>: <span style=\"color:#66d9ef\">BrowserXhr<\/span> },\n<\/span><\/span><span style=\"display:flex;\"><span>  ],\n<\/span><\/span><span style=\"display:flex;\"><span>})\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">export<\/span> <span style=\"color:#66d9ef\">class<\/span> <span style=\"color:#a6e22e\">HttpClientModule<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p>we can tell that <code>HttpHandler<\/code> maps to <code>HttpInterceptingHandler<\/code>:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">@Injectable<\/span>()\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">export<\/span> <span style=\"color:#66d9ef\">class<\/span> <span style=\"color:#a6e22e\">HttpInterceptingHandler<\/span> <span style=\"color:#66d9ef\">implements<\/span> <span style=\"color:#a6e22e\">HttpHandler<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">private<\/span> <span style=\"color:#a6e22e\">chain<\/span>: <span style=\"color:#66d9ef\">HttpHandler<\/span><span style=\"color:#f92672\">|<\/span><span style=\"color:#66d9ef\">null<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">null<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">constructor<\/span>(<span style=\"color:#66d9ef\">private<\/span> <span style=\"color:#a6e22e\">backend<\/span>: <span style=\"color:#66d9ef\">HttpBackend<\/span>, <span style=\"color:#66d9ef\">private<\/span> <span style=\"color:#a6e22e\">injector<\/span>: <span style=\"color:#66d9ef\">Injector<\/span>) {}\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">handle<\/span>(<span style=\"color:#a6e22e\">req<\/span>: <span style=\"color:#66d9ef\">HttpRequest<\/span>&lt;<span style=\"color:#f92672\">any<\/span>&gt;)<span style=\"color:#f92672\">:<\/span> <span style=\"color:#a6e22e\">Observable<\/span>&lt;<span style=\"color:#f92672\">HttpEvent<\/span><span style=\"color:#960050;background-color:#1e0010\">&lt;<\/span><span style=\"color:#a6e22e\">any<\/span>&gt;<span style=\"color:#f92672\">&gt;<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">chain<\/span> <span style=\"color:#f92672\">===<\/span> <span style=\"color:#66d9ef\">null<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">interceptors<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">injector<\/span>.<span style=\"color:#66d9ef\">get<\/span>(<span style=\"color:#a6e22e\">HTTP_INTERCEPTORS<\/span>, []);\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">chain<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">interceptors<\/span>.<span style=\"color:#a6e22e\">reduceRight<\/span>(\n<\/span><\/span><span style=\"display:flex;\"><span>          (<span style=\"color:#a6e22e\">next<\/span>, <span style=\"color:#a6e22e\">interceptor<\/span>) <span style=\"color:#f92672\">=&gt;<\/span> <span style=\"color:#66d9ef\">new<\/span> <span style=\"color:#a6e22e\">HttpInterceptorHandler<\/span>(<span style=\"color:#a6e22e\">next<\/span>, <span style=\"color:#a6e22e\">interceptor<\/span>), <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">backend<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>    }\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">chain<\/span>.<span style=\"color:#a6e22e\">handle<\/span>(<span style=\"color:#a6e22e\">req<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>  }\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p><code>HttpInterceptingHandler<\/code> constructs the <strong>interceptor chain<\/strong>, which will in the end allow us to <strong>apply<\/strong> all the <strong>registered interceptors<\/strong> to the request.<\/p>\n<p>We can also see that <code>HttpInterceptingHandler<\/code> <strong>implements<\/strong> <code>HttpHandler<\/code>:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">export<\/span> <span style=\"color:#66d9ef\">abstract<\/span> <span style=\"color:#66d9ef\">class<\/span> <span style=\"color:#a6e22e\">HttpHandler<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">abstract<\/span> <span style=\"color:#a6e22e\">handle<\/span>(<span style=\"color:#a6e22e\">req<\/span>: <span style=\"color:#66d9ef\">HttpRequest<\/span>&lt;<span style=\"color:#f92672\">any<\/span>&gt;)<span style=\"color:#f92672\">:<\/span> <span style=\"color:#a6e22e\">Observable<\/span>&lt;<span style=\"color:#f92672\">HttpEvent<\/span><span style=\"color:#960050;background-color:#1e0010\">&lt;<\/span><span style=\"color:#a6e22e\">any<\/span>&gt;<span style=\"color:#f92672\">&gt;<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p><code>HttpHandler<\/code> is implemented by <code>HttpBackend<\/code><\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">export<\/span> <span style=\"color:#66d9ef\">abstract<\/span> <span style=\"color:#66d9ef\">class<\/span> <span style=\"color:#a6e22e\">HttpBackend<\/span> <span style=\"color:#66d9ef\">implements<\/span> <span style=\"color:#a6e22e\">HttpHandler<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">abstract<\/span> <span style=\"color:#a6e22e\">handle<\/span>(<span style=\"color:#a6e22e\">req<\/span>: <span style=\"color:#66d9ef\">HttpRequest<\/span>&lt;<span style=\"color:#f92672\">any<\/span>&gt;)<span style=\"color:#f92672\">:<\/span> <span style=\"color:#a6e22e\">Observable<\/span>&lt;<span style=\"color:#f92672\">HttpEvent<\/span><span style=\"color:#960050;background-color:#1e0010\">&lt;<\/span><span style=\"color:#a6e22e\">any<\/span>&gt;<span style=\"color:#f92672\">&gt;<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p><code>HttpBackend<\/code> is implemented by <code>HttpXhrBackend<\/code>, which will eventually <strong>send the request<\/strong> to the server(More on this here).<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">@Injectable<\/span>()\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">export<\/span> <span style=\"color:#66d9ef\">class<\/span> <span style=\"color:#a6e22e\">HttpXhrBackend<\/span> <span style=\"color:#66d9ef\">implements<\/span> <span style=\"color:#a6e22e\">HttpBackend<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">constructor<\/span>(<span style=\"color:#66d9ef\">private<\/span> <span style=\"color:#a6e22e\">xhrFactory<\/span>: <span style=\"color:#66d9ef\">XhrFactory<\/span>) {}\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">handle<\/span>(<span style=\"color:#a6e22e\">req<\/span>: <span style=\"color:#66d9ef\">HttpRequest<\/span>&lt;<span style=\"color:#f92672\">any<\/span>&gt;)<span style=\"color:#f92672\">:<\/span> <span style=\"color:#a6e22e\">Observable<\/span>&lt;<span style=\"color:#f92672\">HttpEvent<\/span><span style=\"color:#960050;background-color:#1e0010\">&lt;<\/span><span style=\"color:#a6e22e\">any<\/span>&gt;<span style=\"color:#f92672\">&gt;<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#75715e\">\/* ... *\/<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>  }\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p>As you can see, both <code>HttpInterceptingHandler<\/code> and <code>HttpXhrBackend<\/code> will have to <strong>implement<\/strong> the <code>handle()<\/code> method.<br>\nConsequently, the solution to this problem would be to make <code>HttpHandler<\/code> map to <code>HttpXhrBackend<\/code>.<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">@NgModule<\/span>({\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">imports<\/span><span style=\"color:#f92672\">:<\/span> [\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#75715e\">\/* ... *\/<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">HttpClientModule<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#75715e\">\/* ... *\/<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>  ],\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">declarations<\/span><span style=\"color:#f92672\">:<\/span> [ <span style=\"color:#75715e\">\/* ... *\/<\/span> ],\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">providers<\/span><span style=\"color:#f92672\">:<\/span> [\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#75715e\">\/* ... *\/<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>    {\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#a6e22e\">provide<\/span>: <span style=\"color:#66d9ef\">HttpHandler<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#a6e22e\">useExisting<\/span>: <span style=\"color:#66d9ef\">HttpXhrBackend<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>    },\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#75715e\">\/* ... *\/<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>  ]\n<\/span><\/span><span style=\"display:flex;\"><span>})\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">export<\/span> <span style=\"color:#66d9ef\">class<\/span> <span style=\"color:#a6e22e\">AppModule<\/span> { }\n<\/span><\/span><\/code><\/pre><\/div><h2 id=\"what-is-the-difference-between-setheaders-and-headers\">\n  <span>\n  What is the difference between <code>setHeaders<\/code> and <code>headers<\/code>?\n  <\/span>\n  <a href=\"#what-is-the-difference-between-setheaders-and-headers\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><h3 id=\"setheaders\">\n  <span>\n  <code>setHeaders<\/code>\n  <\/span>\n  <a href=\"#setheaders\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h3><div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">req<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">req<\/span>.<span style=\"color:#a6e22e\">clone<\/span>({\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">setHeaders<\/span><span style=\"color:#f92672\">:<\/span> { <span style=\"color:#a6e22e\">foo<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;bar&#39;<\/span> },\n<\/span><\/span><span style=\"display:flex;\"><span>})\n<\/span><\/span><\/code><\/pre><\/div><p>With <code>setHeaders<\/code>, we can <strong>append<\/strong> the provided headers to the existing ones.<\/p>\n<h3 id=\"headers\">\n  <span>\n  <code>headers<\/code>\n  <\/span>\n  <a href=\"#headers\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h3><div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">req<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">req<\/span>.<span style=\"color:#a6e22e\">clone<\/span>({\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">setHeaders<\/span><span style=\"color:#f92672\">:<\/span> { <span style=\"color:#a6e22e\">foo<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;bar&#39;<\/span> },\n<\/span><\/span><span style=\"display:flex;\"><span>})\n<\/span><\/span><\/code><\/pre><\/div><p>With <code>headers<\/code>(an instance of <code>HttpHeaders<\/code>), we can <strong>override<\/strong> the <strong>existing<\/strong> headers.<\/p>\n<p>Here is the excerpt from the sources:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ Headers and params may be appended to if `setHeaders` or\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ `setParams` are used.\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span><span style=\"color:#66d9ef\">let<\/span> <span style=\"color:#a6e22e\">headers<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">update<\/span>.<span style=\"color:#a6e22e\">headers<\/span> <span style=\"color:#f92672\">||<\/span> <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">headers<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">let<\/span> <span style=\"color:#a6e22e\">params<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">update<\/span>.<span style=\"color:#a6e22e\">params<\/span> <span style=\"color:#f92672\">||<\/span> <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">params<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ Check whether the caller has asked to add headers.\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span><span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#a6e22e\">update<\/span>.<span style=\"color:#a6e22e\">setHeaders<\/span> <span style=\"color:#f92672\">!==<\/span> <span style=\"color:#66d9ef\">undefined<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#75715e\">\/\/ Set every requested header.\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>  <span style=\"color:#a6e22e\">headers<\/span> <span style=\"color:#f92672\">=<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>      Object.<span style=\"color:#a6e22e\">keys<\/span>(<span style=\"color:#a6e22e\">update<\/span>.<span style=\"color:#a6e22e\">setHeaders<\/span>)\n<\/span><\/span><span style=\"display:flex;\"><span>          .<span style=\"color:#a6e22e\">reduce<\/span>((<span style=\"color:#a6e22e\">headers<\/span>, <span style=\"color:#a6e22e\">name<\/span>) <span style=\"color:#f92672\">=&gt;<\/span> <span style=\"color:#a6e22e\">headers<\/span>.<span style=\"color:#66d9ef\">set<\/span>(<span style=\"color:#a6e22e\">name<\/span>, <span style=\"color:#a6e22e\">update<\/span>.<span style=\"color:#a6e22e\">setHeaders<\/span> <span style=\"color:#f92672\">!<\/span>[<span style=\"color:#a6e22e\">name<\/span>]), <span style=\"color:#a6e22e\">headers<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><blockquote>\n<p>The same goes for <code>setParams<\/code> &amp; <code>params<\/code>.<\/p>\n<\/blockquote>\n<h2 id=\"whats-the-magic-behind-httpheaders\">\n  <span>\n  What&rsquo;s the magic behind <code>HttpHeaders<\/code>?\n  <\/span>\n  <a href=\"#whats-the-magic-behind-httpheaders\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><p><code>HttpHeaders<\/code> is a class that allows us to manipulate(perform <strong>CRUD operations<\/strong> on) headers for our requests.<\/p>\n<p>Have a look at this example:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">headers<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">new<\/span> <span style=\"color:#a6e22e\">HttpHeaders<\/span>({\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">foo<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;foo&#39;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">bar<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;bar&#39;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>});\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">newHeaders<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">headers<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>  .<span style=\"color:#a6e22e\">append<\/span>(<span style=\"color:#e6db74\">&#39;name&#39;<\/span>, <span style=\"color:#e6db74\">&#39;andrei&#39;<\/span>)\n<\/span><\/span><span style=\"display:flex;\"><span>  .<span style=\"color:#66d9ef\">set<\/span>(<span style=\"color:#e6db74\">&#39;city&#39;<\/span>, <span style=\"color:#e6db74\">&#39;tgv&#39;<\/span>)\n<\/span><\/span><span style=\"display:flex;\"><span>  .<span style=\"color:#66d9ef\">delete<\/span>(<span style=\"color:#e6db74\">&#39;foo&#39;<\/span>)\n<\/span><\/span><span style=\"display:flex;\"><span>  .<span style=\"color:#a6e22e\">has<\/span>(<span style=\"color:#e6db74\">&#39;abcd&#39;<\/span>);\n<\/span><\/span><\/code><\/pre><\/div><p>The magic about this is that it will only initialize the headers(<strong>key-value pairs<\/strong>) when they are actually needed. That is, when you want to query for their current state(<code>HttpHeaders.forEach()<\/code>, <code>HttpHeaders.get()<\/code> etc&hellip;).<\/p>\n<p>Here&rsquo;s how the constructor looks like:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">constructor<\/span>(<span style=\"color:#a6e22e\">headers?<\/span>: <span style=\"color:#66d9ef\">string<\/span><span style=\"color:#f92672\">|<\/span>{[<span style=\"color:#a6e22e\">name<\/span>: <span style=\"color:#66d9ef\">string<\/span>]<span style=\"color:#f92672\">:<\/span> <span style=\"color:#66d9ef\">string<\/span> <span style=\"color:#f92672\">|<\/span> <span style=\"color:#66d9ef\">string<\/span>[]}) {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#f92672\">!<\/span><span style=\"color:#a6e22e\">headers<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">headers<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">new<\/span> <span style=\"color:#a6e22e\">Map<\/span>&lt;<span style=\"color:#f92672\">string<\/span><span style=\"color:#960050;background-color:#1e0010\">,<\/span> <span style=\"color:#a6e22e\">string<\/span><span style=\"color:#960050;background-color:#1e0010\">[]<\/span>&gt;();\n<\/span><\/span><span style=\"display:flex;\"><span>  } <span style=\"color:#66d9ef\">else<\/span> <span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#66d9ef\">typeof<\/span> <span style=\"color:#a6e22e\">headers<\/span> <span style=\"color:#f92672\">===<\/span> <span style=\"color:#e6db74\">&#39;string&#39;<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">lazyInit<\/span> <span style=\"color:#f92672\">=<\/span> () <span style=\"color:#f92672\">=&gt;<\/span> { <span style=\"color:#75715e\">\/* ... *\/<\/span> }\n<\/span><\/span><span style=\"display:flex;\"><span>  } <span style=\"color:#66d9ef\">else<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">lazyInit<\/span> <span style=\"color:#f92672\">=<\/span> () <span style=\"color:#f92672\">=&gt;<\/span> { <span style=\"color:#75715e\">\/* ... *\/<\/span> }\n<\/span><\/span><span style=\"display:flex;\"><span>  }\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p>As we can see, the <code>lazyInit<\/code> function is initialized in the constructor of <code>HttpHeaders<\/code>.<br>\nAs a result, in order to perform actions such as <code>HttpHeaders.append<\/code>, <code>HttpHeaders.set<\/code> or <code>HttpHeaders.delete<\/code>, which would eventually mutate the <strong>initial state<\/strong> that was provided to the <strong>constructor<\/strong>, there will be a clone created that will store the new actions(<code>create<\/code> -&gt; <code>set<\/code>, <code>update<\/code> -&gt; <code>append<\/code>, <code>delete<\/code> -&gt; <code>delete<\/code>).<br>\nThese <strong>stored actions<\/strong> will be <strong>merged<\/strong> with the <strong>initial state<\/strong> in the end.<\/p>\n<p>Here&rsquo;s how the <code>HttpHeaders.clone<\/code> looks like:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ action\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span><span style=\"color:#66d9ef\">interface<\/span> <span style=\"color:#a6e22e\">Update<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">name<\/span>: <span style=\"color:#66d9ef\">string<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">value?<\/span>: <span style=\"color:#66d9ef\">string<\/span><span style=\"color:#f92672\">|<\/span><span style=\"color:#66d9ef\">string<\/span>[];\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">op<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;a&#39;<\/span><span style=\"color:#f92672\">|<\/span><span style=\"color:#e6db74\">&#39;s&#39;<\/span><span style=\"color:#f92672\">|<\/span><span style=\"color:#e6db74\">&#39;d&#39;<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">private<\/span> <span style=\"color:#a6e22e\">clone<\/span>(<span style=\"color:#a6e22e\">update<\/span>: <span style=\"color:#66d9ef\">Update<\/span>)<span style=\"color:#f92672\">:<\/span> <span style=\"color:#a6e22e\">HttpHeaders<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">clone<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">new<\/span> <span style=\"color:#a6e22e\">HttpHeaders<\/span>();\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#75715e\">\/\/ Preserve the initialization across multiple clones\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>  <span style=\"color:#a6e22e\">clone<\/span>.<span style=\"color:#a6e22e\">lazyInit<\/span> <span style=\"color:#f92672\">=<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>      (<span style=\"color:#f92672\">!!<\/span><span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">lazyInit<\/span> <span style=\"color:#f92672\">&amp;&amp;<\/span> <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">lazyInit<\/span> <span style=\"color:#66d9ef\">instanceof<\/span> <span style=\"color:#a6e22e\">HttpHeaders<\/span>) <span style=\"color:#f92672\">?<\/span> <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">lazyInit<\/span> : <span style=\"color:#66d9ef\">this<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#75715e\">\/\/ Accumulate actions \n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>  <span style=\"color:#a6e22e\">clone<\/span>.<span style=\"color:#a6e22e\">lazyUpdate<\/span> <span style=\"color:#f92672\">=<\/span> (<span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">lazyUpdate<\/span> <span style=\"color:#f92672\">||<\/span> []).<span style=\"color:#a6e22e\">concat<\/span>([<span style=\"color:#a6e22e\">update<\/span>]);\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#a6e22e\">clone<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p>Let&rsquo;s understand this logic by using our initial example:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">headers<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">new<\/span> <span style=\"color:#a6e22e\">HttpHeaders<\/span>({\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">foo<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;foo&#39;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">bar<\/span><span style=\"color:#f92672\">:<\/span> <span style=\"color:#e6db74\">&#39;bar&#39;<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>});\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/* \n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">--&gt;\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">h1.lazyInit = () =&gt; {\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">  \/\/ Initialize headers\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">}\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">*\/<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">newHeaders<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">headers<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>  .<span style=\"color:#a6e22e\">append<\/span>(<span style=\"color:#e6db74\">&#39;name&#39;<\/span>, <span style=\"color:#e6db74\">&#39;andrei&#39;<\/span>)\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#75715e\">\/* \n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">  --&gt;\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">  \/\/ Creating a clone\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">  h2.lazyInit = h1 \/\/ Preserving the first `instance` across multiple clones\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">  h2.lazyUpdate = { &#34;name&#34;: &#34;name&#34;, &#34;value&#34;: &#34;andrei&#34;, &#34;op&#34;: &#34;a&#34; }\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">  *\/<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>  .<span style=\"color:#66d9ef\">set<\/span>(<span style=\"color:#e6db74\">&#39;city&#39;<\/span>, <span style=\"color:#e6db74\">&#39;tgv&#39;<\/span>)\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#75715e\">\/* \n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">  --&gt;\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">  \/\/ Creating a clone\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">  \/\/ h2.lazyInit = h1\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">  h3.lazyInit = h2.lazyInit \/\/ Preserving the first `instance` across multiple clones\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">  h3.lazyUpdate = [\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">    { &#34;name&#34;: &#34;name&#34;, &#34;value&#34;: &#34;andrei&#34;, &#34;op&#34;: &#34;a&#34; }, \/\/ append\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">    { &#34;name&#34;: &#34;city&#34;, &#34;value&#34;: &#34;tgv&#34;, &#34;op&#34;: &#34;s&#34; } \/\/ set\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">  ]\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">  *\/<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>  .<span style=\"color:#66d9ef\">delete<\/span>(<span style=\"color:#e6db74\">&#39;foo&#39;<\/span>)\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#75715e\">\/* \n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">  --&gt;\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">  \/\/ Creating a clone\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">  \/\/ h3.lazyInit = h2.lazyInit\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">  h4.lazyInit = h3.lazyInit \/\/ Preserving the first `instance` across multiple clones\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">  h4.lazyUpdate = [\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">    { &#34;name&#34;: &#34;name&#34;, &#34;value&#34;: &#34;andrei&#34;, &#34;op&#34;: &#34;a&#34; },\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">    { &#34;name&#34;: &#34;city&#34;, &#34;value&#34;: &#34;tgv&#34;, &#34;op&#34;: &#34;s&#34; },\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">    { &#34;name&#34;: &#34;foo&#34;, &#34;op&#34;: &#34;d&#34; }\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">  ]\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">  *\/<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>  .<span style=\"color:#a6e22e\">has<\/span>(<span style=\"color:#e6db74\">&#39;abcd&#39;<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#75715e\">\/* \n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">  --&gt;\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">  Here is where the initialization takes place\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">  *\/<\/span>\n<\/span><\/span><\/code><\/pre><\/div><p>The <strong>merging process<\/strong> would look like this:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">private<\/span> <span style=\"color:#a6e22e\">init<\/span>()<span style=\"color:#f92672\">:<\/span> <span style=\"color:#66d9ef\">void<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#f92672\">!!<\/span><span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">lazyInit<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">lazyInit<\/span> <span style=\"color:#66d9ef\">instanceof<\/span> <span style=\"color:#a6e22e\">HttpHeaders<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">copyFrom<\/span>(<span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">lazyInit<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>    } <span style=\"color:#66d9ef\">else<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">lazyInit<\/span>();\n<\/span><\/span><span style=\"display:flex;\"><span>    }\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">lazyInit<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">null<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#f92672\">!!<\/span><span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">lazyUpdate<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">lazyUpdate<\/span>.<span style=\"color:#a6e22e\">forEach<\/span>(<span style=\"color:#a6e22e\">update<\/span> <span style=\"color:#f92672\">=&gt;<\/span> <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">applyUpdate<\/span>(<span style=\"color:#a6e22e\">update<\/span>));\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">lazyUpdate<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">null<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>    }\n<\/span><\/span><span style=\"display:flex;\"><span>  }\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">private<\/span> <span style=\"color:#a6e22e\">copyFrom<\/span>(<span style=\"color:#a6e22e\">other<\/span>: <span style=\"color:#66d9ef\">HttpHeaders<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">other<\/span>.<span style=\"color:#a6e22e\">init<\/span>();\n<\/span><\/span><span style=\"display:flex;\"><span>  Array.<span style=\"color:#66d9ef\">from<\/span>(<span style=\"color:#a6e22e\">other<\/span>.<span style=\"color:#a6e22e\">headers<\/span>.<span style=\"color:#a6e22e\">keys<\/span>()).<span style=\"color:#a6e22e\">forEach<\/span>(<span style=\"color:#a6e22e\">key<\/span> <span style=\"color:#f92672\">=&gt;<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">headers<\/span>.<span style=\"color:#66d9ef\">set<\/span>(<span style=\"color:#a6e22e\">key<\/span>, <span style=\"color:#a6e22e\">other<\/span>.<span style=\"color:#a6e22e\">headers<\/span>.<span style=\"color:#66d9ef\">get<\/span>(<span style=\"color:#a6e22e\">key<\/span>) <span style=\"color:#f92672\">!<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">normalizedNames<\/span>.<span style=\"color:#66d9ef\">set<\/span>(<span style=\"color:#a6e22e\">key<\/span>, <span style=\"color:#a6e22e\">other<\/span>.<span style=\"color:#a6e22e\">normalizedNames<\/span>.<span style=\"color:#66d9ef\">get<\/span>(<span style=\"color:#a6e22e\">key<\/span>) <span style=\"color:#f92672\">!<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>  });\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p>The <code>HttpHeaders.init()<\/code> method is called when querying for the state of the headers(by using methods like <code>HttpHeaders.get()<\/code>, <code>HttpHeaders.has()<\/code>)<\/p>\n<p>In <code>HttpHeaders.copyFrom()<\/code>, <code>other<\/code> will be the first instance of <code>HttpHeaders<\/code>, which contains the initialization logic: <code>lazyInit<\/code>. Calling <code>other.init()<\/code> will eventually reach this part of the <code>HttpHeaders.init()<\/code>: <code>this.lazyInit();<\/code>. Here the initial state is created into the first instance.<\/p>\n<p>We are then left with two other things to do:<\/p>\n<ol>\n<li>\n<p>copy the state of the first instance into this current instance(<em>last clone<\/em>); this is achieved in these lines from <code>HttpHeaders.copyFrom()<\/code>:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span>Array.<span style=\"color:#66d9ef\">from<\/span>(<span style=\"color:#a6e22e\">other<\/span>.<span style=\"color:#a6e22e\">headers<\/span>.<span style=\"color:#a6e22e\">keys<\/span>()).<span style=\"color:#a6e22e\">forEach<\/span>(<span style=\"color:#a6e22e\">key<\/span> <span style=\"color:#f92672\">=&gt;<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">headers<\/span>.<span style=\"color:#66d9ef\">set<\/span>(<span style=\"color:#a6e22e\">key<\/span>, <span style=\"color:#a6e22e\">other<\/span>.<span style=\"color:#a6e22e\">headers<\/span>.<span style=\"color:#66d9ef\">get<\/span>(<span style=\"color:#a6e22e\">key<\/span>) <span style=\"color:#f92672\">!<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">normalizedNames<\/span>.<span style=\"color:#66d9ef\">set<\/span>(<span style=\"color:#a6e22e\">key<\/span>, <span style=\"color:#a6e22e\">other<\/span>.<span style=\"color:#a6e22e\">normalizedNames<\/span>.<span style=\"color:#66d9ef\">get<\/span>(<span style=\"color:#a6e22e\">key<\/span>) <span style=\"color:#f92672\">!<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>});\n<\/span><\/span><\/code><\/pre><\/div><\/li>\n<li>\n<p>apply the collected actions onto the copied state:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ HttpHeaders.init()\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span><span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#f92672\">!!<\/span><span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">lazyUpdate<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">lazyUpdate<\/span>.<span style=\"color:#a6e22e\">forEach<\/span>(<span style=\"color:#a6e22e\">update<\/span> <span style=\"color:#f92672\">=&gt;<\/span> <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">applyUpdate<\/span>(<span style=\"color:#a6e22e\">update<\/span>));\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">lazyUpdate<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">null<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><\/li>\n<\/ol>\n<h2 id=\"what-about-httpclientjsonpmodule\">\n  <span>\n  What about <code>HttpClientJsonpModule<\/code>?\n  <\/span>\n  <a href=\"#what-about-httpclientjsonpmodule\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><p><a href=\"https:\/\/en.wikipedia.org\/wiki\/JSONP\" target=\"_blank\" rel=\"noopener\">JSONP<\/a> is a way to solve the well-known <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/HTTP\/CORS\" target=\"_blank\" rel=\"noopener\">CORS<\/a> issue. It does so by treating the resource as a <code>script<\/code> file.<\/p>\n<p>When we are requesting a resource with the <code>script<\/code> tag we can pass along a <strong>defined callback<\/strong> which the resource will eventually wrap the json response in. The <strong>callback<\/strong> will be <strong>called while<\/strong> the <code>script<\/code> is <strong>loading<\/strong>.<\/p>\n<p>This module provides as a way to use <strong>JSONP<\/strong> without worrying too much about the aforementioned details.<\/p>\n<p>Let&rsquo;s quickly explore it and see why it is awesome!<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">@NgModule<\/span>({\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">providers<\/span><span style=\"color:#f92672\">:<\/span> [\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">JsonpClientBackend<\/span>,\n<\/span><\/span><span style=\"display:flex;\"><span>    {<span style=\"color:#a6e22e\">provide<\/span>: <span style=\"color:#66d9ef\">JsonpCallbackContext<\/span>, <span style=\"color:#a6e22e\">useFactory<\/span>: <span style=\"color:#66d9ef\">jsonpCallbackContext<\/span>},\n<\/span><\/span><span style=\"display:flex;\"><span>    {<span style=\"color:#a6e22e\">provide<\/span>: <span style=\"color:#66d9ef\">HTTP_INTERCEPTORS<\/span>, <span style=\"color:#a6e22e\">useClass<\/span>: <span style=\"color:#66d9ef\">JsonpInterceptor<\/span>, <span style=\"color:#a6e22e\">multi<\/span>: <span style=\"color:#66d9ef\">true<\/span>},\n<\/span><\/span><span style=\"display:flex;\"><span>  ],\n<\/span><\/span><span style=\"display:flex;\"><span>})\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">export<\/span> <span style=\"color:#66d9ef\">class<\/span> <span style=\"color:#a6e22e\">HttpClientJsonpModule<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p><strong>JsonpCallbackContext<\/strong> maps to <code>jsonpCallbackContext<\/code> which will return either the <strong>window object<\/strong> or an <strong>empty object<\/strong>(used in a testing environment). The returned object is used to <strong>store<\/strong> the <strong>callback<\/strong> which will in the end be called by script.<\/p>\n<p>It also provides an interceptor, namely <code>JsonpInterceptor<\/code>. What this interceptor does is that it makes sure that our request never reaches the HttpBackend(which will contain completely different logic) when the request method is <code>JSONP<\/code>.<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">@Injectable<\/span>()\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">export<\/span> <span style=\"color:#66d9ef\">class<\/span> <span style=\"color:#a6e22e\">JsonpInterceptor<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">constructor<\/span>(<span style=\"color:#66d9ef\">private<\/span> <span style=\"color:#a6e22e\">jsonp<\/span>: <span style=\"color:#66d9ef\">JsonpClientBackend<\/span>) {}\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">intercept<\/span>(<span style=\"color:#a6e22e\">req<\/span>: <span style=\"color:#66d9ef\">HttpRequest<\/span>&lt;<span style=\"color:#f92672\">any<\/span>&gt;, <span style=\"color:#a6e22e\">next<\/span>: <span style=\"color:#66d9ef\">HttpHandler<\/span>)<span style=\"color:#f92672\">:<\/span> <span style=\"color:#a6e22e\">Observable<\/span>&lt;<span style=\"color:#f92672\">HttpEvent<\/span><span style=\"color:#960050;background-color:#1e0010\">&lt;<\/span><span style=\"color:#a6e22e\">any<\/span>&gt;<span style=\"color:#f92672\">&gt;<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#a6e22e\">req<\/span>.<span style=\"color:#a6e22e\">method<\/span> <span style=\"color:#f92672\">===<\/span> <span style=\"color:#e6db74\">&#39;JSONP&#39;<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">jsonp<\/span>.<span style=\"color:#a6e22e\">handle<\/span>(<span style=\"color:#a6e22e\">req<\/span> <span style=\"color:#66d9ef\">as<\/span> <span style=\"color:#a6e22e\">HttpRequest<\/span>&lt;<span style=\"color:#f92672\">never<\/span>&gt;);\n<\/span><\/span><span style=\"display:flex;\"><span>    }\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#75715e\">\/\/ Fall through for normal HTTP requests.\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>    <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#a6e22e\">next<\/span>.<span style=\"color:#a6e22e\">handle<\/span>(<span style=\"color:#a6e22e\">req<\/span>); <span style=\"color:#75715e\">\/\/ Next interceptor in the chain\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>  }\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p><strong>JsonpClientBackend<\/strong> is where the magic happens. It automatically generates a callback that will be called later by the script. It does so by <strong>replacing<\/strong> the <code>JSONP_CALLBACK<\/code> parameter value in the url with the <strong>newly generated callback name<\/strong>.<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">export<\/span> <span style=\"color:#66d9ef\">class<\/span> <span style=\"color:#a6e22e\">JsonpClientBackend<\/span> <span style=\"color:#66d9ef\">implements<\/span> <span style=\"color:#a6e22e\">HttpBackend<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#66d9ef\">private<\/span> <span style=\"color:#a6e22e\">nextCallback<\/span>()<span style=\"color:#f92672\">:<\/span> <span style=\"color:#66d9ef\">string<\/span> { <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#e6db74\">`ng_jsonp_callback_<\/span><span style=\"color:#e6db74\">${<\/span><span style=\"color:#a6e22e\">nextRequestId<\/span><span style=\"color:#f92672\">++<\/span><span style=\"color:#e6db74\">}<\/span><span style=\"color:#e6db74\">`<\/span>; }\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#75715e\">\/* ... *\/<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#a6e22e\">handle<\/span> (<span style=\"color:#75715e\">\/* ... *\/<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#66d9ef\">new<\/span> <span style=\"color:#a6e22e\">Observable<\/span>&lt;<span style=\"color:#f92672\">HttpEvent<\/span><span style=\"color:#960050;background-color:#1e0010\">&lt;<\/span><span style=\"color:#a6e22e\">any<\/span>&gt;<span style=\"color:#f92672\">&gt;<\/span>((<span style=\"color:#a6e22e\">observer<\/span>: <span style=\"color:#66d9ef\">Observer<\/span>&lt;<span style=\"color:#f92672\">HttpEvent<\/span><span style=\"color:#960050;background-color:#1e0010\">&lt;<\/span><span style=\"color:#a6e22e\">any<\/span>&gt;<span style=\"color:#f92672\">&gt;<\/span>) <span style=\"color:#f92672\">=&gt;<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#75715e\">\/* ... *\/<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">callback<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">nextCallback<\/span>();\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">url<\/span> <span style=\"color:#f92672\">=<\/span> <span style=\"color:#a6e22e\">req<\/span>.<span style=\"color:#a6e22e\">urlWithParams<\/span>.<span style=\"color:#a6e22e\">replace<\/span>(<span style=\"color:#e6db74\">\/=JSONP_CALLBACK(&amp;|$)\/<\/span>, <span style=\"color:#e6db74\">`=<\/span><span style=\"color:#e6db74\">${<\/span><span style=\"color:#a6e22e\">callback<\/span><span style=\"color:#e6db74\">}<\/span><span style=\"color:#e6db74\">$1`<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>    });\n<\/span><\/span><span style=\"display:flex;\"><span>  }\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p>Then, it stores the <strong>callback function<\/strong> in the object returned by <code>jsonpCallbackContext<\/code> using the <strong>generated callback name<\/strong>.<\/p>\n<p><code>this.callbackMap[callback] = (data?: any) =&gt; {   delete this.callbackMap[callback];    if (cancelled) {     return;   }    body = data;   finished = true; };<\/code><\/p>\n<p>It is important to notice once again that the above callback should be called <strong>before<\/strong> the script finished downloading. This way, we can <strong>determine whether<\/strong> the <strong>provided callback was called or not<\/strong> in case we decide to provide the callback name ourselves.<br>\nThis is done when the script has finished loading:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ Inside `JsonpClientBackend.handle`\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span><span style=\"color:#66d9ef\">const<\/span> <span style=\"color:#a6e22e\">onLoad<\/span> <span style=\"color:#f92672\">=<\/span> (<span style=\"color:#a6e22e\">event<\/span>: <span style=\"color:#66d9ef\">Event<\/span>) <span style=\"color:#f92672\">=&gt;<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#75715e\">\/\/ Maybe due to `switchMap`\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>    <span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#a6e22e\">cancelled<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#66d9ef\">return<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>    }\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">cleanup<\/span>();\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#75715e\">\/\/ Was the callback called with the response?\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>    <span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#f92672\">!<\/span><span style=\"color:#a6e22e\">finished<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#75715e\">\/\/ If not, send the error response to the stream\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>      \n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#66d9ef\">return<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>    }\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#75715e\">\/\/ If yes, sent the response to the stream - everything was successful\n<\/span><\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\"><\/span>}\n<\/span><\/span><\/code><\/pre><\/div><h2 id=\"conclusion\">\n  <span>\n  Conclusion\n  <\/span>\n  <a href=\"#conclusion\" class=\"anchor\">\n    <svg class=\"fill-current o-60 hover-accent-color-light\" height=\"22\" viewBox=\"0 0 24 24\" width=\"22\"\n      xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n      <path d=\"M0 0h24v24H0z\" fill=\"none\"><\/path>\n      <path\n        d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z\">\n      <\/path>\n    <\/svg>\n  <\/a>\n<\/h2><p>I hope exploring this module was a fun adventure!<\/p>\n<p>Thanks for reading!<\/p>\n"}]}}