<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Ilya Lyamkin</title>
    <description>The latest articles on DEV Community by Ilya Lyamkin (@ilyamkin).</description>
    <link>https://dev.to/ilyamkin</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F251357%2F90aeb6e7-c68f-4be2-9e4d-0ab32b1924f8.jpg</url>
      <title>DEV Community: Ilya Lyamkin</title>
      <link>https://dev.to/ilyamkin</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ilyamkin"/>
    <language>en</language>
    <item>
      <title>What are Web Standards and how does Web Browser work?</title>
      <dc:creator>Ilya Lyamkin</dc:creator>
      <pubDate>Wed, 27 May 2020 13:10:38 +0000</pubDate>
      <link>https://dev.to/catawiki/what-are-web-standards-and-how-does-web-browser-work-3a1k</link>
      <guid>https://dev.to/catawiki/what-are-web-standards-and-how-does-web-browser-work-3a1k</guid>
      <description>&lt;p&gt;Let me tell you a story. Once I was building yet another date picker component for our design system. It consists of text input and pop-up with a calendar that shows by clicking on it. Then pop-up can be closed on click outside or if the date was selected.&lt;/p&gt;

&lt;p&gt;Most implementations of the click outside logic made with actual click listeners attached to the DOM. However, I wanted to build our date picker accessible, so you could open a calendar with tabs and close the same way. Additionally, click listeners may conflict with each other if you put several date pickers on the page.&lt;/p&gt;

&lt;p&gt;What if you could just rely on native focus and blur events instead of detecting clicks outside? They naturally support tabs, touch and click events, and already implemented in the browser. The only problem you need to solve in this case is when you click on the pop-up but without date selection: focus shifts to the calendar, triggering blur event on the text input and eventually closing the pop-up.&lt;/p&gt;

&lt;p&gt;At this point, I started wondering if there is a way to click but do not shift a focus. After quick googling, I found a way to do it: prevent the default action of the &lt;code&gt;mouseDown&lt;/code&gt; event for the pop-up. Just like that in one line, all clicks worked but the focus was still on the text input.&lt;/p&gt;

&lt;p&gt;It seemed like that's the solution, let's move forward, but something inside of me was stopping me from that. Why specifically &lt;code&gt;mouseDown&lt;/code&gt; and not &lt;code&gt;mouseUp&lt;/code&gt; prevents focus but propagates click? Is it some part of the living standards? Can we rely on that? Does it work cross-browser? React Testing Library that we used to do integration tests also didn't support it and I'd have to change simulation function.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Web Standard?
&lt;/h2&gt;

&lt;p&gt;Alright, since the Stack Overflow answer wasn't enough for me, so what could be a better place to learn about browser behavior than the web standards?&lt;/p&gt;

&lt;p&gt;You probably heard about &lt;a href="https://www.w3.org/"&gt;W3C&lt;/a&gt; or World Wide Web Consortium. It's an international community that develops open standards for the Web. W3C makes sure that everyone follows the same guidelines and we don't have to support dozens completely different environments. If you visit their website, you'll find the list of &lt;a href="https://www.w3.org/TR/"&gt;all standards&lt;/a&gt; they're working on.&lt;/p&gt;

&lt;p&gt;Let's have a look at the one document that might have an answer to our questions -  &lt;a href="https://www.w3.org/TR/2019/WD-uievents-20190530/"&gt;UI Events Standard&lt;/a&gt;. This document specifies the DOM event flow, defines a list of events and their execution order. If you thought that standards are boring, obscure, and hard-to-understand text blocks, then jump straight to &lt;a href="https://www.w3.org/TR/2019/WD-uievents-20190530/#dom-event-architecture"&gt;DOM Event Architecture&lt;/a&gt; section that explains event bubbling and capturing with nice pictures and still being very specific as standard supposed to be. You'd be surprised by the quality of it, it's really well-written with a lot of examples and recommendations.&lt;/p&gt;

&lt;p&gt;It also has a definition of our &lt;code&gt;mouseDown&lt;/code&gt; event and its default actions:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Many implementations use the mousedown event to begin a variety of contextually dependent default actions. These default actions can be prevented if this event is canceled. Some of these default actions could include: beginning a drag/drop interaction with an image or link, starting text selection, etc. Additionally, some implementations provide a mouse-driven panning feature that is activated when the middle mouse button is pressed at the time the mousedown event is dispatched."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Alright, so our event has some default actions, but there is nothing specific about focus because it really depends on browser implementations. Let's check them out.&lt;/p&gt;

&lt;h2&gt;
  
  
  Introduction to browser engines
&lt;/h2&gt;

&lt;p&gt;A modern browser is a quite complicated piece of software with the codebase around &lt;a href="https://www.openhub.net/p/chrome/analyses/latest/languages_summary"&gt;tens of millions of lines of code&lt;/a&gt;. So it's usually split into several parts.&lt;/p&gt;

&lt;p&gt;To find a place where focus events are defined, we need to get an overview of what each part is responsible for. Let's start with Chromium and its design documentation &lt;a href="https://www.chromium.org/developers/how-tos/getting-around-the-chrome-source-code"&gt;Getting Around The Chrome Source Code&lt;/a&gt;. As you can see there is a lot of modules responsible for different logic.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--rDRMqAv5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://lyamkin.com/static/48fb9b01019e15ebc2175863dd8f03e6/669eb/chromium.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--rDRMqAv5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://lyamkin.com/static/48fb9b01019e15ebc2175863dd8f03e6/669eb/chromium.png" alt="A high-level overview of Chromium"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's briefly go over them to get the idea of how it works together.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;chrome&lt;/strong&gt;: it's a base app with startup logic, UI, and all windows. It contains the projects for &lt;code&gt;chrome.exe&lt;/code&gt; and &lt;code&gt;chrome.dll&lt;/code&gt;. Resources such as icons or cursors you can also find here.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;content&lt;/strong&gt;: it's a backend of the app which handles communication with child processes.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;net&lt;/strong&gt;: this is the networking library that helps to make queries to websites.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;base&lt;/strong&gt;: a place for common code shared between all sub-projects. This could include things like string manipulation, generic utilities, etc.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;blink&lt;/strong&gt;: it's a rendering engine that responsible for the whole rendering pipeline including DOM trees, styles, events, V8 integration.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;v8&lt;/strong&gt;: a final big part of a browser - Javascript engine. Its job is to compile JavaScript to native machine code.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As you can see browser consist of several independent parts that talk to each other via API. The most interesting parts for developers are usually Blink and V8. Browser defined default actions are not part of V8, but Blink should have all of them defined and implemented. But before we jump into the Blink codebase, let's understand how web browsers work from a user point of view.&lt;/p&gt;

&lt;h2&gt;
  
  
  Rendering pipeline
&lt;/h2&gt;

&lt;p&gt;Imagine you enter domain address in a browser, then it fetches and loads a bunch of assets: HTML, CSS, and JS files, images, icons. But what would happen next?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--TVA88qTh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://lyamkin.com/static/e41e7cf5396a09a2ffcf6cd64aa9b3f0/c83ae/rendering-pipeline.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--TVA88qTh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://lyamkin.com/static/e41e7cf5396a09a2ffcf6cd64aa9b3f0/c83ae/rendering-pipeline.png" alt="Web browser rendering pipeline"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As a first step, HTML files would be parsed and turned into a &lt;strong&gt;DOM tree&lt;/strong&gt;. The DOM is not only the internal representation of the page but also an API exposed to Javascript for querying or modifying the rendering through a system called "bindings".&lt;/p&gt;

&lt;p&gt;After the DOM tree, the next step is to process the CSS styles. For that purpose browsers have a CSS parser that builds a model of the style rules. Having built a model for style rules, we can merge them together with a set of default styles supplied by the browser and compute the final value of every style property for every DOM element. This process is called &lt;strong&gt;style resolving (or recalc)&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;In the next &lt;strong&gt;layout&lt;/strong&gt; part, we need to determine the visual geometry of all the elements. At this stage each element gets its coordinates (x and y), width, and height. The layout engine calculates and keeps records of all overflow areas - which part is visible and which is not.&lt;/p&gt;

&lt;p&gt;As we got all coordinates for all elements, it's time for &lt;strong&gt;painting&lt;/strong&gt;. For this operation, we use coordinates from the previous step and color from style rules and combine them into a list of painting instructions. It's important to paint elements in the right order so that they stack correctly when they overlap. You can modify order via &lt;code&gt;z-index&lt;/code&gt; style rule.&lt;/p&gt;

&lt;p&gt;Let's execute our list of painting instructions and convert them into a bitmap of color values. This stage is called &lt;strong&gt;raster&lt;/strong&gt;. At this moment we also take our images and decode them into bitmap as well.&lt;/p&gt;

&lt;p&gt;Later the rastered bitmap will be stored in &lt;strong&gt;GPU&lt;/strong&gt; memory. This stage includes libraries that abstract the hardware and issuing calls to OpenGL and DirectX on Windows. When GPU receives the instructions to display bitmap, it draws pixels on your screen.&lt;/p&gt;

&lt;p&gt;Now we have the most important parts of the rendering pipeline. But what would happen if you scroll the page, or some animation would be applied? In fact, rendering is not static. Change is represented via &lt;strong&gt;animation frames&lt;/strong&gt;. Each frame is a complete rendering of the state of the content at a particular point in time. The real challenge in this process is its performance. Smooth animations require generation at least 60 frames per second. It would almost impossible to complete a full pipeline 60 times in a second especially on slow devices.&lt;/p&gt;

&lt;p&gt;What if instead of always re-rendering everything, we provide a way to &lt;strong&gt;invalidate&lt;/strong&gt; an element at a specific stage. E.g. if you change the color of the button dynamically, the browser will mark this node as invalidated and it would be re-rerendered on the next animation frame. If nothing is changed we can reuse the old frame.&lt;/p&gt;

&lt;p&gt;That's a good way to optimize small dynamic changes in the content. Let's think about change in big regions of content. For example, if scroll the page, all pixels have to be different now. For that purpose a page is decomposed into layers that raster independently. A layer can be fairly small and represent only one DOM node. Those layers then will be combined together on another thread called &lt;strong&gt;the compositor thread&lt;/strong&gt;. With this optimization you don't need to re-raster everything, but rather do it for small layers and then correctly combine them together.&lt;/p&gt;

&lt;p&gt;Now we have a little overview of what Blink does and how rendering pipeline looks like. Let's dive into the code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Navigating Blink codebase
&lt;/h2&gt;

&lt;p&gt;It seems like we are finally at the finish line. Let's open the &lt;a href="https://chromium.googlesource.com/chromium/blink/+/master/Source"&gt;Blink repository&lt;/a&gt; and look around.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--S5u3M3Cv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://lyamkin.com/static/4c7ba19c91567494a8cdf7a5a1ab420f/b17f8/root-folder.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--S5u3M3Cv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://lyamkin.com/static/4c7ba19c91567494a8cdf7a5a1ab420f/b17f8/root-folder.jpg" alt="The root folder of Blink repository"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We can quickly realize that even though we narrowed down a lot from our original question, it's still too big to manually find a specific line of code responsible for preventing focus.&lt;/p&gt;

&lt;p&gt;Let's try to search by our event name in Google:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;mousedown site:https://chromium.googlesource.com/chromium/blink/+/master/Source
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;It leads us to the &lt;a href="https://chromium.googlesource.com/chromium/blink/+/master/Source/core/input/EventHandler.cpp#972"&gt;EventHandler&lt;/a&gt; file where you can find implementation details for a lot of input events. Including the most important line for us:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;swallowEvent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;dispatchMouseEvent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;EventTypeNames&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;mousedown&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mev&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;innerNode&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;m_clickCount&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mouseEvent&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;code&gt;dispatchMouseEvent&lt;/code&gt; return value means "continue default handling", so &lt;code&gt;swallowEvent&lt;/code&gt; is &lt;code&gt;true&lt;/code&gt; in case of &lt;code&gt;preventDefault&lt;/code&gt; usage.&lt;/p&gt;

&lt;p&gt;Just below there is a call for focus event which is triggered only if &lt;code&gt;swallowEvent == false&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="n"&gt;swallowEvent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;swallowEvent&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="n"&gt;handleMouseFocus&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;MouseEventWithHitTestResults&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mouseEvent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;hitTestResult&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;sourceCapabilities&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Apart from focus handling, you can explore all default actions of the mouse down event including selection, drag-drop, and scrollbar cases. It also implements mouse release and double clicks events - everything is there.&lt;/p&gt;

&lt;h2&gt;
  
  
  Gecko and WebKit
&lt;/h2&gt;

&lt;p&gt;At this point, we already spent some time discovering browsers source code and have a pretty good understanding of their structure, so why not check Firefox and Safari altogether. Firefox's browser engine called Gecko and Safari's - WebKit.&lt;/p&gt;

&lt;p&gt;Gecko also has an &lt;a href="https://wiki.mozilla.org/Gecko:Overview"&gt;overview page&lt;/a&gt; for developers, so you'd get an idea of the main concepts of it. Based on the experience with Chrome, you can find a neat 6000 lines of code &lt;a href="https://github.com/mozilla/gecko-dev/blob/master/dom/events/EventStateManager.cpp#L3177"&gt;EventStateManager&lt;/a&gt; file with events default actions and behavior. I've included a specific line in the link, so you won't have to go through it all.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://webkit.org/"&gt;WebKit&lt;/a&gt; is a browser engine from Apple used in Safari and other Apple products. Chrome's Blink was forked from WebKit, so they have a lot of things in common and it wasn't a problem to find events implementation in their version of &lt;a href="https://github.com/WebKit/webkit/blob/1321fa346ad792f6de3ace65ca98cbe3957a96c6/Source/WebCore/page/EventHandler.cpp#L1757"&gt;EventHandler&lt;/a&gt; file.&lt;/p&gt;

&lt;p&gt;Now since we made sure we can prevent &lt;code&gt;mousedown&lt;/code&gt; event safely, I can step back and finish the PR with the date picker.&lt;/p&gt;

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

&lt;p&gt;Together we went a journey from a simple problem to the introduction of Web Standards and browser implementation details.&lt;/p&gt;

&lt;p&gt;Don't be scared by the hidden complexity of existing modules even if it's a browser or compiler. It will be a fun journey in the end. The chances are you can easily find things to improve, and more importantly, get unique insights into how things actually work. I've learned a ton of stuff during this deep dive and encourage everyone to do the same. Browsers will provide excellent documentation along the way at the point that I'm not sure why I need anything else.&lt;/p&gt;

&lt;h2&gt;
  
  
  Relevant links for further reading
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Do you know what DOM is? How it's represented internally? What's the purpose of events? I'd highly recommend &lt;a href="https://dom.spec.whatwg.org/"&gt;DOM Standard&lt;/a&gt; to everyone from beginners to more experienced developers. &lt;a href="https://dom.spec.whatwg.org/#action-versus-occurance"&gt;"An event signifies an occurrence, not an action."&lt;/a&gt; - my favorite part of it.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Official website of the &lt;a href="https://www.w3.org/"&gt;W3C&lt;/a&gt; community.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.chromium.org/developers/how-tos/getting-around-the-chrome-source-code"&gt;Getting around Chromium codebase&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.chromium.org/developers/design-documents"&gt;Design documents&lt;/a&gt; published by Chromium developers.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://docs.google.com/presentation/d/1boPxbgNrTU0ddsc144rcXayGA_WF53k96imRH8Mp34Y/edit"&gt;Life of a pixel&lt;/a&gt; - introduction into rendering pipeline of Chrome.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>performance</category>
      <category>webstandards</category>
    </item>
    <item>
      <title>How to Build a Dev.to API Client Library in JS</title>
      <dc:creator>Ilya Lyamkin</dc:creator>
      <pubDate>Mon, 27 Apr 2020 18:41:12 +0000</pubDate>
      <link>https://dev.to/ilyamkin/how-to-build-a-dev-to-api-client-library-in-js-3i1j</link>
      <guid>https://dev.to/ilyamkin/how-to-build-a-dev-to-api-client-library-in-js-3i1j</guid>
      <description>&lt;p&gt;Every time I find myself connecting to a third-party API that doesn't have a client library I have to create a lot of boilerplate around it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Manually getting and passing authentication credentials to the data fetching layer. What if you want to persist API keys or perform the OAuth process?&lt;/li&gt;
&lt;li&gt;Defining data models and normalization. You would need to make sure that the data you receive from API is saved in a structured way.&lt;/li&gt;
&lt;li&gt;Create a controller for API that keeps all the methods in one place, so you can easily modify and find all usages of the API across your codebase.&lt;/li&gt;
&lt;li&gt;Keeping up with updates. The APIs tend to change a lot: new methods come, old ones deprecate.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It was one of these days where I decided to connect to &lt;a href="https://docs.dev.to/api/"&gt;Dev.to API&lt;/a&gt; to automatically collect stats for &lt;a href="https://dev.to/ilyamkin"&gt;my published articles&lt;/a&gt;. There wasn't any API client ready for use, so I ended up creating all of the wrapping logic around it. So if it's already there then why not share it with others together with my learnings, right? We'll go through five steps and come out with a clear plan on how to implement your own client.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1. Language and target platform
&lt;/h2&gt;

&lt;p&gt;Before jumping into the coding part, let's discuss which language we're going to use. Remember my point about defining data models? For API client it's essential to give a user more information about data that is going be returned, so we don't have to constantly switch context between documentation and IDE. It also helps to avoid bugs and typos as you write code (we all have tests in the end, haven't we?). Keeping all that in mind, the best choice at the moment is to use Typescript.&lt;/p&gt;

&lt;p&gt;Now let's think where our library is going to be run. Basically, it could a browser or a Node.js server. Why not develop a library that works in both? It'll also make it easier to use it together with server-side rendering where code executed at the server first and then on the client.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2. Bundling
&lt;/h2&gt;

&lt;p&gt;Two major differentiators for any library is its size and support of users with old and modern clients. First, we want our size to be as small as possible - API client shouldn't add much weight to the project. Second, the library should have decent browser support by serving the CommonJS bundle for those who cannot support the modern version and at the same time give a modern bundle for clients with newer versions.&lt;/p&gt;

&lt;p&gt;The default choice for a web project is &lt;a href="https://webpack.js.org/"&gt;Webpack&lt;/a&gt;, but our library is fairly small and simple, so I've chosen &lt;a href="https://rollupjs.org/guide/en/"&gt;Rollup&lt;/a&gt; as base bundler together with &lt;a href="https://github.com/developit/microbundle"&gt;&lt;code&gt;microbundle&lt;/code&gt;&lt;/a&gt; for easy setup.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;npm i &lt;span class="nt"&gt;-D&lt;/span&gt; microbundle
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Now update the &lt;code&gt;package.js&lt;/code&gt; with build tasks and a path to entry point:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"source"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"src/foo.js"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Your&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;source&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;file&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;(same&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;as&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="err"&gt;st&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;arg&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;microbundle)&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"main"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"dist/foo.js"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;           &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;output&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;path&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;CommonJS/Node&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"module"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"dist/foo.module.js"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;output&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;path&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;JS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Modules&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"unpkg"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"dist/foo.umd.js"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;optional&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;unpkg.com&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"scripts"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"build"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"microbundle"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;uses&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"source"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;and&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"main"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;as&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;input&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;and&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;output&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;paths&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;by&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;default&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"dev"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"microbundle watch"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 3. Structure of the library
&lt;/h2&gt;

&lt;p&gt;As we indent to support a lot of API endpoints we want our code to scale well if API expands. One of the best ways to do that is to align folders with resource names. For &lt;a href="https://docs.dev.to/api/"&gt;Dev.to API&lt;/a&gt; it would look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/src
    /articles
        index.ts // Everything that's related to articles
        ...
    /comments
        index.ts
        ...
    /users
        ...
    index.ts // Imports and joins all resources together
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;It also useful to keep resources as separate classes, so you don't need to change root &lt;code&gt;index.ts&lt;/code&gt; every time you add a new method. Then you'd need to merge them together using &lt;a href="https://www.typescriptlang.org/docs/handbook/mixins.html"&gt;Typescript Mixins&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;applyMixins&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;derivedCtor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;any&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;baseCtors&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;any&lt;/span&gt;&lt;span class="p"&gt;[])&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;baseCtors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;baseCtor&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getOwnPropertyNames&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;baseCtor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;prototype&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;defineProperty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
          &lt;span class="nx"&gt;derivedCtor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;prototype&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getOwnPropertyDescriptor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;baseCtor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;prototype&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;DevTo&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;Base&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;DevTo&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;Articles&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Comments&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Users&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="nx"&gt;applyMixins&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;DevTo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;Articles&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Comments&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Users&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;DevTo&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 4. Fetching library
&lt;/h2&gt;

&lt;p&gt;We wanted to make a library that works both in the browser and in Node.js. How we would make our requests universal as well? &lt;code&gt;fetch&lt;/code&gt; is available in the browser but missing in Node.js where you should use the &lt;code&gt;http&lt;/code&gt; module.&lt;br&gt;
&lt;a href="https://github.com/developit/unfetch/tree/master/packages/isomorphic-unfetch"&gt;&lt;code&gt;isomorphic-unfetch&lt;/code&gt;&lt;/a&gt; will help us use fetch function everywhere and switch between browser and Node.js versions automatically.&lt;/p&gt;

&lt;p&gt;Now let's have a look at the &lt;code&gt;request&lt;/code&gt; function which wraps fetch and append authentication header:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;endpoint&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;RequestInit&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;basePath&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;endpoint&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;headers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;api-key&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;apiKey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Content-type&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;application/json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ok&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;statusText&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;We always return &lt;code&gt;Promise&lt;/code&gt;, so clients can chain requests together or wait for the results.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 5. Testing
&lt;/h2&gt;

&lt;p&gt;Most of the code in API client is integration with third-party endpoints. To make testing easier we can utilize the &lt;a href="https://github.com/nock/nock"&gt;Nock&lt;/a&gt; library that conveniently mocks HTTP server for us.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Article resource&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;getArticles returns a list of articles&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Set up the mock request&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;scope&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;nock&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://dev.to/api/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
           &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/articles&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
           &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;reply&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt; &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Article&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}])&lt;/span&gt;

        &lt;span class="c1"&gt;// Make the request&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;DevToClient&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;DevTo&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;apiKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;XYZ&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;DevToClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getArticles&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

        &lt;span class="c1"&gt;// Assert that the expected request was made.&lt;/span&gt;
        &lt;span class="nx"&gt;scope&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;done&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;In the example above we set up the mock, then make the request and finally checking that mock has been executed.&lt;/p&gt;

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

&lt;p&gt;Together we designed an API client that is small, scalable, supports Typescript out-of-the-box, and works in browser and in Node.js.&lt;/p&gt;

&lt;p&gt;I invite everyone to check out the &lt;a href="https://github.com/ilyamkin/dev-to-js"&gt;repository&lt;/a&gt; to collaborate and improve the library. If you ever wanted to be a maintainer of an open-source library, this is something I'd be open to help.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>showdev</category>
      <category>opensource</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Why Hackathons Make You a Better Developer</title>
      <dc:creator>Ilya Lyamkin</dc:creator>
      <pubDate>Sat, 30 Nov 2019 18:04:47 +0000</pubDate>
      <link>https://dev.to/ilyamkin/why-hackathons-make-you-a-better-developer-2lej</link>
      <guid>https://dev.to/ilyamkin/why-hackathons-make-you-a-better-developer-2lej</guid>
      <description>&lt;p&gt;Over the course of my life, I’ve participated in more than 20 hackathons, so I might be a little biased on them, but on the other hand, I know a lot about how they can be useful.&lt;/p&gt;

&lt;p&gt;Let me start by explaining what a hackathon means to me. In general, it’s an event of short duration (usually one or two days) where people come together to creatively solve problems. Hackathons can be themed, where the projects are confined to a particular problem such as food sustainability or returning citizens.&lt;/p&gt;

&lt;h1&gt;
  
  
  Reasons to Participate in Hackathons
&lt;/h1&gt;

&lt;p&gt;Now that we have covered the definition, we can start with the reasons why you’ll become a better developer by participating in hackathons.&lt;/p&gt;

&lt;h2&gt;
  
  
  Extreme programming
&lt;/h2&gt;

&lt;p&gt;It’s very easy to forget about speed while working with Scrum processes, so let’s bring the former back. With short deadlines and ambitious ideas, hackathons teach you how to code fast and, more importantly, think fast.&lt;/p&gt;

&lt;p&gt;If you’re wondering why it’s that important, the reason is that you’ll know your limits much better and will be able to push them even further after the hackathon. You’ll not only be surprised by how much you have achieved but also understand your areas of growth.&lt;/p&gt;

&lt;h2&gt;
  
  
  Learning how to estimate your efforts better
&lt;/h2&gt;

&lt;p&gt;Due to the limited time, proper estimation is essential for your success. If your estimation is incorrect, you won’t be able to achieve what you planned in time. &lt;/p&gt;

&lt;p&gt;The truth is, at a hackathon, you’ll notice that your estimations are far from perfect. Use this fact to your advantage and adjust your estimations so that it doesn’t happen at work.&lt;/p&gt;

&lt;h2&gt;
  
  
  Creative thinking
&lt;/h2&gt;

&lt;p&gt;Hackathons teach you how to solve a known problem creatively. In the first stage, ideation, you have to come up with a unique and fresh idea. If you think that’s all, actually, this is just the beginning. Now it’s time for execution, and you have to be creative at every step of the way because you’ll never have enough time or well-defined processes. Something will always break most unexpectedly, and you’ll need to find a viable solution to be able to ship the product in time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Learning new technology
&lt;/h2&gt;

&lt;p&gt;Hackathons are perfect places to learn something new. If you use React.js at work, try Svelte. Writing back-end with Java? Learn Kotlin! Or completely switch your stack from front end to back end, and the other way around. Maybe you want to get into VR. This is your chance.&lt;/p&gt;

&lt;h2&gt;
  
  
  Networking
&lt;/h2&gt;

&lt;p&gt;Hackathon is an excellent chance to talk to fellow developers and like-minded people. You can get a big picture of what they’re working on and which tools they’re currently using. Think of it as a conference where you also have to code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Iteration-based approach
&lt;/h2&gt;

&lt;p&gt;At hackathons, you should focus on building a minimum viable product, which means you should be able to drop parts that are not required and then iterate over it. That’d allow you to ship a product where you can show something to people even if you can’t finish this cool new feature in time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Learning how to split tasks in the best way
&lt;/h2&gt;

&lt;p&gt;If your team consists of four or five people, you have to make sure your team works as one organism and utilizes the abilities of each team member. Be ready to communicate with your team actively and split the product into several independent pieces. Without proper separation of concerns, four people would work as two with clearly divided tasks.&lt;/p&gt;

&lt;h2&gt;
  
  
  Shifting focus to bring business value
&lt;/h2&gt;

&lt;p&gt;In our work, you can easily forget why you’re writing code and what value it brings to the end-user. On the other hand, at hackathons, you’re solving real-world challenges — and thinking about them in the first place. It shifts your vision from just code to a big picture of what you’re trying to archive.&lt;/p&gt;

&lt;h2&gt;
  
  
  Workshops
&lt;/h2&gt;

&lt;p&gt;It’s popular to have workshops that you can attend at the time of the event. They could be about new technology or about soft skills like improving your resume. They can be highly beneficial if you have just started your career or want to learn something new.&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting feedback
&lt;/h2&gt;

&lt;p&gt;Hackathons are one of the best places for validating your ideas. In your normal life, it’s hard to find someone who will be both honest and willing to spend time reviewing your ideas. Other options include using your personal network or paying for ads. At hackathons, you get all of that for free, and from people like you.&lt;/p&gt;

&lt;h2&gt;
  
  
  Giving feedback
&lt;/h2&gt;

&lt;p&gt;I know a lot of people who find joy in helping and teaching others. By doing so, you can learn what others are doing and, if you have expertise in that area, help them. The best way to grow your network is to be helpful, so actively seek out these opportunities.&lt;/p&gt;

&lt;h2&gt;
  
  
  Having fun
&lt;/h2&gt;

&lt;p&gt;Ultimately, this is what hackathons are all about. Don’t worry if you’re not going to be able to present a perfect product, just have fun. If your hackathon takes place in a different city or country, take advantage. Get to know the local culture and engage in unique experiences.&lt;/p&gt;

&lt;h1&gt;
  
  
  How To Get Started
&lt;/h1&gt;

&lt;p&gt;If you decide to give hackathons a chance, there are several resources to check out.&lt;br&gt;
The first is Major League Hacking (MLH). It’s the official student hackathon league that runs over &lt;a href="https://mlh.io/seasons/na-2020/events"&gt;200 weekend-long invention competitions&lt;/a&gt;.&lt;br&gt;
Second, make sure to go over &lt;a href="https://www.hackjunction.com/"&gt;Junction Hackathon&lt;/a&gt; and &lt;a href="https://techcrunch.com/events/disrupt-sf-2019/hackathon/"&gt;TechCrunch Disrupt Hackathon&lt;/a&gt;. They’re one of the biggest independent hackathons in the world.&lt;br&gt;
Last but not least, check &lt;a href="https://www.meetup.com/"&gt;Meetup&lt;/a&gt; to find local hackathons in your city.&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;I hope I convinced you to take a look at hackathons. It would definitely not be easy to code for two days non-stop, but the results will pay off. You’ll learn a lot about yourself and your limits, find out how to estimate and split tasks, and understand how to apply your skills to solve real-world challenges. And don’t forget to have fun.&lt;/p&gt;

</description>
      <category>hackathon</category>
      <category>devrel</category>
      <category>productivity</category>
      <category>career</category>
    </item>
    <item>
      <title>You Might Not Need Controlled Components</title>
      <dc:creator>Ilya Lyamkin</dc:creator>
      <pubDate>Wed, 27 Nov 2019 20:31:57 +0000</pubDate>
      <link>https://dev.to/ilyamkin/you-might-not-need-controlled-components-ei8</link>
      <guid>https://dev.to/ilyamkin/you-might-not-need-controlled-components-ei8</guid>
      <description>&lt;p&gt;If you'll go to the official React website it says that &lt;a href="https://reactjs.org/docs/uncontrolled-components.html"&gt;the recommended way to use inputs is to control them via React state&lt;/a&gt;. It also mentions that in some cases you can go with an uncontrolled option but do not say what are these cases explicitly. Let’s try to dive into it and see the pros and cons of this approach.&lt;/p&gt;

&lt;h1&gt;
  
  
  It’s all about control
&lt;/h1&gt;

&lt;p&gt;Controlled input values are being kept in the local state. Every time the user changes the content of the input, the &lt;code&gt;onChange&lt;/code&gt; function updates the React state, Component rerenders with the new value passed to Input.&lt;/p&gt;


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


&lt;h1&gt;
  
  
  Let browser do its job
&lt;/h1&gt;

&lt;p&gt;On the other hand, uncontrolled inputs are being handled by the browser itself. So you don’t have direct control over inputs value in the component, but you can use ref to get access to it.&lt;/p&gt;


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


&lt;p&gt;Looking at these two examples you can clearly say that the second one looks cleaner and less verbose than the first one. You don’t need to instantiate state, pass the value to each input and override &lt;code&gt;onChange&lt;/code&gt; handlers.&lt;/p&gt;

&lt;p&gt;An uncontrolled form doesn’t have state, so every time you type, your component doesn’t re-render, increasing overall performance.&lt;/p&gt;

&lt;p&gt;By leveraging uncontrolled inputs you’re trusting browser with form management and become closer to the native implementation. Why do you need to write something that was already created anyway? 🤔&lt;/p&gt;

&lt;h2&gt;
  
  
  But what if I need to handle complex form, perform validation or handle custom submit logic?
&lt;/h2&gt;

&lt;p&gt;Use refs. With new Hooks API, refs became a more stable and better way to control DOM. Consider the following example where you need to access forms values outside of the &lt;code&gt;onSubmit&lt;/code&gt; function.&lt;/p&gt;


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


&lt;h2&gt;
  
  
  Embrace HTML5
&lt;/h2&gt;

&lt;p&gt;Browser API provides you with a lot of useful features to handle forms and inputs.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/HTMLFormElement/reset"&gt;&lt;code&gt;form.reset()&lt;/code&gt;&lt;/a&gt; — use the reset function to clear all your fields&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/HTMLFormElement/submit"&gt;&lt;code&gt;form.submit()&lt;/code&gt;&lt;/a&gt; — use it to programmatically submit the form&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/HTMLFormElement/reportValidity"&gt;&lt;code&gt;form.reportValidity()&lt;/code&gt;&lt;/a&gt; — checks validation constraints and returns &lt;code&gt;true&lt;/code&gt; or &lt;code&gt;false&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Document/forms"&gt;&lt;code&gt;document.forms&lt;/code&gt;&lt;/a&gt; — interface that allows you to access all forms on the page.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/HTML5/Constraint_validation"&gt;Constraint Validation API&lt;/a&gt; — set of properties and methods that allows you to create complex validations on the fields. &lt;code&gt;min&lt;/code&gt;, &lt;code&gt;max&lt;/code&gt;, &lt;code&gt;pattern&lt;/code&gt;, &lt;code&gt;email&lt;/code&gt;, &lt;code&gt;required&lt;/code&gt; — all of that and much more is covered by it.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What about libraries that I can use with uncontrolled inputs?
&lt;/h2&gt;

&lt;p&gt;Sure! &lt;a href="https://github.com/react-hook-form/react-hook-form"&gt;React-Hook-Form&lt;/a&gt; allows you to build a form and perform validation on it without the hassle. &lt;a href="https://github.com/Rocketseat/unform"&gt;Unform&lt;/a&gt; helps you build complex forms with nested fields, validation using uncontrolled components.&lt;/p&gt;

&lt;h2&gt;
  
  
  When it makes sense to use controlled inputs then?
&lt;/h2&gt;

&lt;p&gt;Basically you need to choose controlled inputs when &lt;em&gt;you need to re-render&lt;/em&gt; your component on every type. For example, you want to display or send all form values as you type (imagine autocomplete field for the search bar). Or if you need to pass input value to child component through props. There are quite a few cases where you have to use it.&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;I believe that uncontrolled components are currently undervalued and should have more presence in modern React applications. Indeed they’re not gonna solve all your problems but would help increase the performance and reliability of your components in many cases.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>react</category>
      <category>opensource</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Adventuring Into React Hooks Performance Practices</title>
      <dc:creator>Ilya Lyamkin</dc:creator>
      <pubDate>Thu, 07 Nov 2019 19:41:06 +0000</pubDate>
      <link>https://dev.to/ilyamkin/adventuring-into-react-hooks-performance-practices-5825</link>
      <guid>https://dev.to/ilyamkin/adventuring-into-react-hooks-performance-practices-5825</guid>
      <description>&lt;p&gt;From version 16.8.0, React introduced us to a way to use state and other React features without writing a class — &lt;a href="https://reactjs.org/docs/hooks-intro.html"&gt;React Hooks&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;It’s an amazing improvement around &lt;a href="https://reactjs.org/docs/react-component.html"&gt;the classic Class paradigm&lt;/a&gt; which allows us to reuse stateful logic between components. No surprise that it comes with a learning curve that could lead to performance pitfalls.&lt;/p&gt;

&lt;p&gt;Let’s deep dive into the most popular ones and try to figure out how to avoid them.&lt;/p&gt;

&lt;h2&gt;
  
  
  Re-Renders Matter
&lt;/h2&gt;

&lt;p&gt;Alright, we identified that we may encounter some performance issues while using Hooks, but where are they coming from?&lt;/p&gt;

&lt;p&gt;Essentially, most of the issues with Hooks come from unnecessary renders of your components. Have a look at the following example:&lt;/p&gt;

&lt;p&gt;&lt;iframe src="https://codesandbox.io/embed/incrementor-46w3y"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;This is a component that has two states, A and B, and four increment actions on them. I’ve added the &lt;code&gt;console.log&lt;/code&gt; method to see the message on every render. The first two actions are basic increments and just increase A or B values by one.&lt;/p&gt;

&lt;p&gt;Let’s click on the &lt;em&gt;a++&lt;/em&gt;, &lt;em&gt;b++&lt;/em&gt; button and have a look at the console: on each click, there should be only one render. This is really good because that’s what we wanted.&lt;/p&gt;

&lt;p&gt;Now press the &lt;em&gt;a++, b++ after 1s&lt;/em&gt; button: on each click, you’d see two renders. If you’re wondering what’s happening underneath — the answer is simple.&lt;br&gt;
React batches synchronous state updates into one.&lt;/p&gt;

&lt;p&gt;On the other hand, for asynchronous functions, each &lt;code&gt;setState&lt;/code&gt; function triggers a render method.&lt;/p&gt;

&lt;p&gt;But what if you want to have consistent behavior? Here comes the first rule of Hooks.&lt;/p&gt;
&lt;h2&gt;
  
  
  Rule 1: Do Not Split State Between Several useState Methods for Connected Data Models
&lt;/h2&gt;

&lt;p&gt;Imagine you have two independent states. Then, the requirements changed, thus update of one state causes an update of another one.&lt;br&gt;
In this case, you have to join them in one object: &lt;code&gt;const { A, B } = useState({ A: 0, B: 0})&lt;/code&gt;. Or, take advantage of the &lt;a href="https://reactjs.org/docs/hooks-reference.html#usereducer"&gt;&lt;code&gt;useReducer&lt;/code&gt;&lt;/a&gt; function.&lt;/p&gt;

&lt;p&gt;Another good example of this rule is data loading. Usually, you need three variables to handle it: &lt;code&gt;isLoading&lt;/code&gt;, &lt;code&gt;data&lt;/code&gt;, and &lt;code&gt;error&lt;/code&gt;. Don’t try to keep them separate, prefer &lt;code&gt;useReducer&lt;/code&gt; instead.&lt;/p&gt;

&lt;p&gt;It allows you to separate state logic from components and helps you to avoid bugs. Having one object with these three properties will be a solution as well but would not be that explicit and error-prone.&lt;/p&gt;

&lt;p&gt;Trust me on that, I have seen so many people forgetting to set &lt;code&gt;isLoading: false&lt;/code&gt; on error.&lt;/p&gt;
&lt;h2&gt;
  
  
  Custom Hooks
&lt;/h2&gt;

&lt;p&gt;Now that we’ve figured out how to manage &lt;code&gt;useState&lt;/code&gt; in a single component, let’s move increment functionality outside to be used in different places.&lt;/p&gt;


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


&lt;p&gt;We refactored the increment logic to its own Hook and then we run it once using the &lt;a href="https://reactjs.org/docs/hooks-reference.html#useeffect"&gt;&lt;code&gt;useEffect&lt;/code&gt;&lt;/a&gt; function.&lt;/p&gt;

&lt;p&gt;Note that we have to provide the &lt;code&gt;incrementA&lt;/code&gt; setter in the dependency array because we’re using it inside and it’s enforced by &lt;a href="https://www.npmjs.com/package/eslint-plugin-react-hooks"&gt;Hook’s ESLint rules&lt;/a&gt;. (Please enable them if you didn’t do that before!).&lt;/p&gt;

&lt;p&gt;If you try to render this component, your page will be frozen because of infinite re-renders. To fix it, we need to define the second rule of Hooks.&lt;/p&gt;

&lt;h2&gt;
  
  
  Rule 2. Make Sure You Return New Objects From Custom Hooks Only If They’ve Changed
&lt;/h2&gt;

&lt;p&gt;The component above is always re-rendering because the increment Hook returns a new function every time. To avoid creating a new function every time, wrap it in the &lt;a href="https://reactjs.org/docs/hooks-reference.html#usecallback"&gt;&lt;code&gt;useCallback&lt;/code&gt;&lt;/a&gt; function.&lt;/p&gt;


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


&lt;p&gt;Now it’s safe to use this Hook.&lt;/p&gt;

&lt;p&gt;Sometimes, you need to return a plain object from custom Hooks, make sure you update it only when its content changes using &lt;a href="https://reactjs.org/docs/hooks-reference.html#usememo"&gt;&lt;code&gt;useMemo&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to Find These Re-Renders Before It’s Too Late?
&lt;/h2&gt;

&lt;p&gt;Normally, it’s troublesome to find these issues before it causes performance issues, so you have to use specific tools to detect them beforehand.&lt;/p&gt;

&lt;p&gt;One of them is the &lt;a href="https://github.com/welldone-software/why-did-you-render"&gt;&lt;code&gt;why-did-you-render&lt;/code&gt;&lt;/a&gt; library that tells you about avoidable re-renders. Mark your component as &lt;code&gt;MyComponent.whyDidYouRender = true&lt;/code&gt;, start interacting with it, and look for messages in the console.&lt;/p&gt;

&lt;p&gt;I guarantee that you’ll discover something new in the next five minutes.&lt;/p&gt;

&lt;p&gt;Another option is to use the Profiler tab in &lt;a href="https://github.com/facebook/react/tree/master/packages/react-devtools"&gt;React Dev Tools extension&lt;/a&gt;. Although you have to think about how many re-renders you expect from your component— this tab only shows the number of re-renders.&lt;/p&gt;

&lt;p&gt;Let me know what other challenges you’ve encountered with Hooks, let’s solve them together.&lt;/p&gt;

&lt;h2&gt;
  
  
  References and Further Resources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://reactjs.org/docs/hooks-reference.html"&gt;React Hooks API&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://kentcdodds.com/blog/profile-a-react-app-for-performance/"&gt;How to profile React apps with Dev Tools Profiler&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>react</category>
      <category>webdev</category>
      <category>javascript</category>
      <category>performance</category>
    </item>
    <item>
      <title>Implementing the Prefetch Pattern in React Concurrent Mode</title>
      <dc:creator>Ilya Lyamkin</dc:creator>
      <pubDate>Tue, 05 Nov 2019 23:04:56 +0000</pubDate>
      <link>https://dev.to/ilyamkin/implementing-the-prefetch-pattern-in-react-concurrent-mode-1oed</link>
      <guid>https://dev.to/ilyamkin/implementing-the-prefetch-pattern-in-react-concurrent-mode-1oed</guid>
      <description>&lt;p&gt;Recently, React announced a feature of the React ecosystem — &lt;a href="https://reactjs.org/docs/concurrent-mode-intro.html"&gt;Concurrent Mode&lt;/a&gt;. This would allow us to stop or delay the execution of components for the time that we need. It’ll help React apps stay responsive and gracefully adjust to the user’s device capabilities and network speed.&lt;/p&gt;

&lt;p&gt;Concurrent Mode consists of a set of new features — one of the biggest ones is suspense and a new approach to data fetching.&lt;/p&gt;

&lt;p&gt;Basically, there are three ways to do it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Fetch-on-render:&lt;/strong&gt; We start rendering components and each of these components may trigger data fetching in their effects and lifecycle methods. A good example of that is &lt;code&gt;fetch&lt;/code&gt; in &lt;code&gt;useEffect&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fetch-then-render:&lt;/strong&gt; Start fetching all the data for the next screen as early as possible. When the data is ready, render the new screen. We can’t do anything until the data arrives. The example of that is having a &lt;code&gt;Container&lt;/code&gt; component that handles data fetching and conditionally renders the child presentational component once we’ve received everything.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Render-as-you-fetch:&lt;/strong&gt; Start fetching all the required data for the next screen as early as possible, and start rendering the new screen immediately, even before we get a network response. As data streams in, React retries rendering components that still need data until they’re all ready.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I believe that the concepts of the first two approaches are well known and definitely presented in your code. Let’s dive straight into the render-as-you-fetch approach.&lt;/p&gt;

&lt;h1&gt;
  
  
  Render-As-You-Fetch
&lt;/h1&gt;

&lt;p&gt;You’ve probably noticed that the explanation of this approach has two parts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Start loading data as early as possible.&lt;/li&gt;
&lt;li&gt;Start trying to render components that may still need data.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Fetch early
&lt;/h3&gt;

&lt;p&gt;Let’s build an app together that loads major stock indexes. For that, we have a simple “Load” button. Once you click on it, we start loading data immediately:&lt;/p&gt;


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


&lt;p&gt;&lt;code&gt;prefetchQuery&lt;/code&gt; is a function that performs the &lt;code&gt;fetch&lt;/code&gt; request and returns an object that we’re going to pass to the &lt;code&gt;&amp;lt;IndexList /&amp;gt;&lt;/code&gt; component. The key takeaway from this example is that we’re triggering fetch from the &lt;code&gt;onClick&lt;/code&gt; event and not in the render phase.&lt;/p&gt;

&lt;h2&gt;
  
  
  Render early with Suspense
&lt;/h2&gt;

&lt;p&gt;The second part of the example above is that we’re saving the object from &lt;code&gt;prefetchQuery&lt;/code&gt; to the state and starting to render &lt;code&gt;&amp;lt;IndexList /&amp;gt;&lt;/code&gt; immediately as well.&lt;/p&gt;

&lt;p&gt;On the other hand, we also don’t want to render the list with empty data, so ideally, we’d like to be able to suspend render until we have all the data without writing &lt;code&gt;if (isLoading) return null&lt;/code&gt;. Luckily, we have &lt;a href="https://reactjs.org/docs/concurrent-mode-suspense.html"&gt;the &lt;code&gt;Suspense&lt;/code&gt; component&lt;/a&gt; for exactly that purpose.&lt;/p&gt;

&lt;p&gt;Suspense is a mechanism for data-fetching libraries to communicate to React that &lt;em&gt;the data a component is reading is not ready yet&lt;/em&gt;. React can then wait for it to be ready and update the UI.&lt;/p&gt;

&lt;p&gt;Let me show you an example:&lt;/p&gt;


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


&lt;p&gt;To take advantage of Suspense, you just need to wrap your component with it. It accepts a &lt;code&gt;fallback&lt;/code&gt; prop: the element that you want to show while waiting for data.&lt;/p&gt;

&lt;h3&gt;
  
  
  How To Fetch Data in Sync With Suspense?
&lt;/h3&gt;

&lt;p&gt;Now that you know about Suspense and prefetch practices, you wonder how this all works together. So, here is the last piece of this puzzle. To solve it, let’s finally check out the &lt;code&gt;prefetchQuery&lt;/code&gt; function.&lt;/p&gt;


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


&lt;p&gt;Don’t be scared by the complexity of it, it’s actually fairly simple.&lt;br&gt;
First, we take a URL and pass it to the native &lt;code&gt;fetch&lt;/code&gt; function, receive a promise, and pass it to the &lt;code&gt;wrapPromise&lt;/code&gt; function. This function returns an object with the &lt;code&gt;read()&lt;/code&gt; method:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If a promise is still pending, we throw this promise.&lt;/li&gt;
&lt;li&gt;If a promise is resolved with error, we throw the error.&lt;/li&gt;
&lt;li&gt;If a promise is resolved, just return the data.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In fact, the only difference we have, compared to traditional fetching practices, is throwing a pending promise.&lt;/p&gt;

&lt;p&gt;When you have &lt;code&gt;usePrefetchedQuery&lt;/code&gt; in &lt;code&gt;IndexList&lt;/code&gt;, it just executes the &lt;code&gt;read()&lt;/code&gt; method. If data is not there yet, it throws a promise before actually rendering anything and Suspense will catch that.&lt;/p&gt;
&lt;h1&gt;
  
  
  How To Experiment With This?
&lt;/h1&gt;

&lt;p&gt;The React team introduced &lt;a href="https://reactjs.org/docs/concurrent-mode-adoption.html"&gt;an experimental releases&lt;/a&gt; branch with a modern API.&lt;br&gt;
For that, you need to run &lt;code&gt;npm i react@experimental react-dom@experimental&lt;/code&gt; and play with it locally. I also created a live example on &lt;a href="https://codesandbox.io/s/prefetch-suspense-6q4gj"&gt;CodeSandbox&lt;/a&gt; for you that shows everything I did together in one working project.&lt;br&gt;
&lt;iframe src="https://codesandbox.io/embed/prefetch-suspense-6q4gj"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h1&gt;
  
  
  Can I Use It in My Production Projects?
&lt;/h1&gt;

&lt;p&gt;&lt;strong&gt;No.&lt;/strong&gt; Concurrent mode is still under development and some implementation details could change. Use experimental versions to get familiar with new concepts and maybe propose your own ideas. For example, how to integrate prefetch practices in routers or provide a good way to cache data.&lt;/p&gt;

&lt;h1&gt;
  
  
  Further Resources
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://relay.dev/docs/en/experimental/a-guided-tour-of-relay"&gt;An experimental version of Relay with Suspense.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Soon, you’ll be able to connect preload functionality to routers. Have a look at &lt;a href="https://github.com/ReactTraining/react-router/pull/7010"&gt;https://github.com/ReactTraining/react-router/pull/7010&lt;/a&gt; or &lt;a href="https://github.com/frontarm/navi"&gt;Navi router&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://reactjs.org/docs/concurrent-mode-intro.html"&gt;Introduction to Concurrent mode.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://reactjs.org/docs/concurrent-mode-suspense.html"&gt;Introduction to Suspense for data fetching.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://codesandbox.io/s/prefetch-suspense-6q4gj"&gt;Live sandbox with examples.&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

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