<?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>Forem: Charles Stover</title>
    <description>The latest articles on Forem by Charles Stover (@charlesstover).</description>
    <link>https://forem.com/charlesstover</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%2F174352%2F94d9a9c1-8ca4-4e62-b72a-c19f5e91667d.jpeg</url>
      <title>Forem: Charles Stover</title>
      <link>https://forem.com/charlesstover</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/charlesstover"/>
    <language>en</language>
    <item>
      <title>Manage your customers’ clipboard with React hooks.</title>
      <dc:creator>Charles Stover</dc:creator>
      <pubDate>Tue, 08 Oct 2019 02:25:10 +0000</pubDate>
      <link>https://forem.com/charlesstover/manage-your-customers-clipboard-with-react-hooks-7n</link>
      <guid>https://forem.com/charlesstover/manage-your-customers-clipboard-with-react-hooks-7n</guid>
      <description>&lt;p&gt;Modern web applications have an abundance of tools available for improving user experience. When implementing a new feature, a sizable chunk of UI/UX discussion is typically devoted to reducing the number of necessary clicks and keystrokes required to perform a task. The ability to &lt;em&gt;automate&lt;/em&gt; the repetitive or predictable behavior is one of the largest driving forces behind the software industry, and I think it is beautiful that we have blossomed from calculators saving hours of error-prone manual labor to user interfaces automating seconds.&lt;br&gt;
It is no shock that most large projects inevitably reach a point where we can predict that the user is going to want to copy or paste something, and we inevitably attempt to automate that workflow. Clipboard interactions are one of the oldest attempts to hijack a user’s system for their own good, and it is time that these APIs integrate with React.&lt;/p&gt;

&lt;p&gt;In this article, I will walk through how I created &lt;a href="https://www.npmjs.com/package/use-clippy"&gt;&lt;code&gt;use-clippy&lt;/code&gt;&lt;/a&gt;, a React Hook for writing to or reading from the user’s clipboard. &lt;em&gt;Not to be confused with Microsoft Office’s assistant, Clippy 📎.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This package was interesting to develop for a few reasons:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Clipboard APIs are &lt;em&gt;old&lt;/em&gt; — so old that they have been deprecated and re-invented. We want to make sure that all users, regardless of their browser version, are able to use this feature.&lt;/li&gt;
&lt;li&gt;Clipboard APIs are both synchronous and asynchronous, and we need to account for not knowing whether the action will occur immediately or with delay.&lt;/li&gt;
&lt;li&gt;Clipboard APIs, being a security concern, are permission-based in modern browsers. The primary reason they are asynchronous is due to the time between you attempt to hijack the user’s clipboard and the customer actually approving the permission request.&lt;/li&gt;
&lt;li&gt;Clipboard APIs are not integrated into TypeScript by default. &lt;a href="https://www.npmjs.com/package/use-clippy"&gt;&lt;code&gt;use-clippy&lt;/code&gt;&lt;/a&gt; is a TypeScript package, so we have the joy of writing those types ourselves.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  “I don’t care how it works. I just want it now.” ⏳
&lt;/h2&gt;

&lt;p&gt;You can install &lt;a href="https://www.npmjs.com/package/use-clippy"&gt;&lt;code&gt;use-clippy&lt;/code&gt;&lt;/a&gt; from NPM with &lt;code&gt;npm install use-clippy&lt;/code&gt; or &lt;code&gt;yarn add use-clippy&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Using this package is as easy and intuitive as the &lt;code&gt;useState&lt;/code&gt; React Hook.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;useClippy&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;use-clippy&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;MyComponent&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="nx"&gt;clipboard&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setClipboard&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useClippy&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Just use &lt;code&gt;clipboard&lt;/code&gt; to read the contents of the user’s clipboard, and use &lt;code&gt;setClipboard&lt;/code&gt; to set the contents of the user’s clipboard. It’s that easy.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.npmjs.com/package/use-clippy"&gt;&lt;code&gt;use-clippy&lt;/code&gt;&lt;/a&gt; is also &lt;a href="https://github.com/CharlesStover/use-clippy"&gt;open source on GitHub&lt;/a&gt;. The source code is available for anyone to peruse, and public contributions are welcome.&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating a Hook 🎣
&lt;/h2&gt;

&lt;p&gt;I always start every project by imagining how I would want to interact with the package as a consumer/developer. As a React hook, I want an interface that is intuitive. As such, &lt;a href="https://www.npmjs.com/package/use-clippy"&gt;&lt;code&gt;use-clippy&lt;/code&gt;&lt;/a&gt; is patterned after &lt;code&gt;useState&lt;/code&gt;, the built-in React hook for managing a value and its setter.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;clipboard&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setClipboard&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useClippy&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With this interface, I have read and write capabilities for the clipboard that match my existing component state management code.&lt;/p&gt;

&lt;p&gt;As a TypeScript project, everything will be strongly typed. While there are no parameters to &lt;code&gt;useClippy&lt;/code&gt;, there is a return value, which is defined as such:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;type ClipboardTuple = [
  string,                      // getter for the clipboard value
  (clipboard: string) =&amp;gt; void, // setter for the clipboard value
];
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first thing we’ll need to do is copy the clipboard into a local state for this React component so that changes trigger a re-render.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;useClippy&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nx"&gt;ClipboardTuple&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="nx"&gt;clipboard&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setClipboard&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="nx"&gt;clipboard&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt; &lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;While the clipboard value in the state should match the user’s clipboard value (with a browser-enforced delay as the user authorizes permission to do this), the &lt;code&gt;setClipboard&lt;/code&gt; function here only sets the local React state value, but not the user’s actual clipboard value. Therefore, that is not the function we will be returning to the component consuming &lt;code&gt;useClippy&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Clipboard API 📋
&lt;/h2&gt;

&lt;p&gt;There are two ways to read from a clipboard. Modern browsers have an asynchronous, permission-based clipboard API. A developer may request access to a user’s clipboard, at which point the browser prompts the user to authorize this behavior. Older browsers have a synchronous clipboard API, wherein the developer simply tells the browser to read or write to the clipboard, and the browser simply does it or refuses, with no user interaction.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;useClippy&lt;/code&gt; accounts for both.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Determine if the asynchronous clipboard API is enabled.&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;IS_CLIPBOARD_API_ENABLED&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nb"&gt;navigator&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;object&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
  &lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;navigator&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;ClipboardNavigator&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;clipboard&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;object&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Why “as ClipboardNavigator”?
&lt;/h3&gt;

&lt;p&gt;TypeScript does not contain the Clipboard API in its definition of the &lt;code&gt;navigator&lt;/code&gt; object, despite it being there in many browsers. We must override TypeScript’s definitions in a few places to essentially say, “We know better.”&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// In addition to the navigator object, we also have a clipboard&lt;/span&gt;
&lt;span class="c1"&gt;//   property.&lt;/span&gt;
&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;ClipboardNavigator&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;Navigator&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;clipboard&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Clipboard&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;ClipboardEventTarget&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// The Clipboard API supports readText and writeText methods.&lt;/span&gt;
&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;Clipboard&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;readText&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="kr"&gt;string&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;writeText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// A ClipboardEventTarget is an EventTarget that additionally&lt;/span&gt;
&lt;span class="c1"&gt;//   supports clipboard events (copy, cut, and paste).&lt;/span&gt;
&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;ClipboardEventTarget&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;EventTarget&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="kd"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;copy&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;eventListener&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ClipboardEventListener&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="kd"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;cut&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;eventListener&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ClipboardEventListener&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="kd"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;paste&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;eventListener&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ClipboardEventListener&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;removeEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="kd"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;copy&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;eventListener&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ClipboardEventListener&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;removeEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="kd"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;cut&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;eventListener&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ClipboardEventListener&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;removeEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="kd"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;paste&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;eventListener&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ClipboardEventListener&lt;/span&gt;
  &lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// A ClipboardEventListener is an event listener that accepts a&lt;/span&gt;
&lt;span class="c1"&gt;//   ClipboardEvent.&lt;/span&gt;
&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;ClipboardEventListener&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
  &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nx"&gt;EventListenerObject&lt;/span&gt;
  &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;
  &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ClipboardEvent&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now that we know if the asynchronous Clipboard API is enabled, we can use it with graceful degradation.&lt;/p&gt;

&lt;h3&gt;
  
  
  Re-render when the clipboard is updated.
&lt;/h3&gt;

&lt;p&gt;The asynchronous Clipboard API allows us to subscribe to clipboard changes. We can use this to synchronize our React component’s local state value to the user’s actual clipboard value.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// If the user manually updates their clipboard, re-render with the&lt;/span&gt;
&lt;span class="c1"&gt;//   new value.&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;IS_CLIPBOARD_API_ENABLED&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="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;clipboardListener&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;...;&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="na"&gt;nav&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ClipboardNavigator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
      &lt;span class="nb"&gt;navigator&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;ClipboardNavigator&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;nav&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;clipboard&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;copy&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;clipboardListener&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;nav&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;clipboard&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;cut&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;clipboardListener&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;nav&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;clipboard&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;removeEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;copy&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nx"&gt;clipboardListener&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nx"&gt;nav&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;clipboard&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;removeEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;cut&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nx"&gt;clipboardListener&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="nx"&gt;clipboard&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;Since &lt;code&gt;IS_CLIPBOARD_API_ENABLED&lt;/code&gt; is true, we know that navigator is a &lt;code&gt;ClipboardNavigator&lt;/code&gt; as defined above, so we override TypeScript’s definition. When the user updates their clipboard by copying or cutting, we want this component to re-render with the new value, because this component is reading the user’s clipboard. When the component unmounts, we remove these event listeners. The current &lt;code&gt;clipboard&lt;/code&gt; value is a dependency, because we use it in the clipboard listener to only re-render the component if the new value is different than the old value.&lt;/p&gt;

&lt;p&gt;The clipboard event listener is defined below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;clipboardListener&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;clipboardData&lt;/span&gt; &lt;span class="p"&gt;}:&lt;/span&gt; &lt;span class="nx"&gt;ClipboardEvent&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="na"&gt;cd&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;DataTransfer&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="nx"&gt;clipboardData&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;window&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;ClipboardDataWindow&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;clipboardData&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt;
    &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cd&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;cd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;text/plain&lt;/span&gt;&lt;span class="dl"&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;clipboard&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;setClipboard&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Get the &lt;code&gt;clipboardData&lt;/code&gt; from the event itself. In some cases, it is instead defined on the &lt;code&gt;window&lt;/code&gt; object. If the user did not allow us to read this value, we may instead receive &lt;code&gt;null&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Again, TypeScript does not support the Clipboard API in its definitions, so we must manually define &lt;code&gt;window&lt;/code&gt; as an object that may contain a &lt;code&gt;clipboardData&lt;/code&gt; property.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;ClipboardDataWindow&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;Window&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;clipboardData&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;DataTransfer&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the user did authorize us to read the clipboard, we use &lt;code&gt;getData&lt;/code&gt; to convert our &lt;code&gt;DataTransfer&lt;/code&gt; object to plain text. Only if the new clipboard contents differ from the ones we already have, we set our React component’s local state value to the new clipboard value.&lt;/p&gt;

&lt;h2&gt;
  
  
  Initial Clipboard Value 🔰
&lt;/h2&gt;

&lt;p&gt;Above, we allowed our component to update asynchronously as the customer updates their clipboard. However, when the component first mounts, we need to read the clipboard immediately. Here, we may attempt to read the clipboard &lt;em&gt;synchronously&lt;/em&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Try to read synchronously.&lt;/span&gt;
&lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;read&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;clipboard&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;setClipboard&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;text&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;Reading a clipboard synchronously through older browser APIs is a complex process, so it has been abstracted away and defined below. If it occurs successfully, however, we can set the React local state value to the clipboard value.&lt;/p&gt;

&lt;h3&gt;
  
  
  Reading the clipboard synchronously.
&lt;/h3&gt;

&lt;p&gt;In order to read the clipboard synchronously, we must first &lt;em&gt;paste&lt;/em&gt; the clipboard somewhere.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;read&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="kr"&gt;string&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;// Create a temporary input solely to paste.&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;createInput&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;focus&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="c1"&gt;// Attempt to synchronously paste.&lt;/span&gt;
  &lt;span class="c1"&gt;// (Will return true on success, false on failure.)&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;success&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;execCommand&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;paste&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="c1"&gt;// If we don't have permission to read the clipboard, cleanup and&lt;/span&gt;
  &lt;span class="c1"&gt;//   throw an error.&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;success&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;removeInput&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="nx"&gt;NOT_ALLOWED_ERROR&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="c1"&gt;// Grab the value, remove the temporary input, then return the&lt;/span&gt;
  &lt;span class="c1"&gt;//   value.&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;removeInput&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;i&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;value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Creating and removing the temporary input is more of a CSS tutorial — a challenge in the art of hiding the input from user perception while still being accessible to the browser API. An input that has a display value of &lt;code&gt;none&lt;/code&gt; or a height or width of &lt;code&gt;0&lt;/code&gt; cannot be interacted with. If you are interested, you may &lt;a href="https://github.com/CharlesStover/use-clippy/blob/master/src/use-clippy.ts#L53"&gt;inspect the source code&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Initializing the local state value asynchronously.
&lt;/h3&gt;

&lt;p&gt;When synchronous initialization fails, we can fallback to the slower, but modern asynchronous Clipboard API. If it is enabled, simply read from it and set the local state.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// If synchronous reading is disabled, try to read asynchronously.&lt;/span&gt;
&lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;IS_CLIPBOARD_API_ENABLED&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;nav&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ClipboardNavigator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;navigator&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;ClipboardNavigator&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;nav&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;clipboard&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;readText&lt;/span&gt;&lt;span class="p"&gt;()&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;text&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;clipboard&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nx"&gt;setClipboard&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;text&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="c1"&gt;// Fail silently if an error occurs.&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If both synchronous and asynchronous attempts to read the clipboard failed, there is simply nothing we can do. The browser does not support it, and we fail silently.&lt;/p&gt;

&lt;h2&gt;
  
  
  Set the Clipboard ✍
&lt;/h2&gt;

&lt;p&gt;At the very beginning, we created a tuple that contains the clipboard’s value for reading the user’s clipboard and a setter for setting the user’s clipboard. We have now implemented the first item in that tuple, and it is now time to create the setter.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;clippySetter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;setClipboard&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;IS_CLIPBOARD_API_ENABLED&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="na"&gt;nav&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ClipboardNavigator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
        &lt;span class="nb"&gt;navigator&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;ClipboardNavigator&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nx"&gt;nav&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;clipboard&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;writeText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nx"&gt;setClipboard&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;})&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{});&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first thing we do is attempt to write to the clipboard synchronously. We do this with the same complex behavioral pattern we used for reading synchronously.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;write&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="k"&gt;void&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;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;createInput&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;value&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;select&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;success&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;execCommand&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;copy&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;removeInput&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;success&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="nx"&gt;NOT_ALLOWED_ERROR&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create an input, give it the value we want in the customer’s clipboard, select the contents of that input, then execute a copy command. It will either succeed to synchronously set the user’s clipboard, or it will throw an error.&lt;/p&gt;

&lt;p&gt;In the event it was successful, we set the React component local state to the new value, keeping it in sync with the actual clipboard.&lt;/p&gt;

&lt;p&gt;In the event of an error, we fallback to the asynchronous Clipboard API. If it succeeds to writeText, we set the React component local state to the new value. If it does not succeed, we fail silently.&lt;/p&gt;

&lt;h2&gt;
  
  
  Always update. 🆕
&lt;/h2&gt;

&lt;p&gt;When reading the clipboard, we would only set the React local state if the new value was different than the existing value. When setting the clipboard, we always set the user’s clipboard and the React local state, even if the new value is the same as the existing one.&lt;/p&gt;

&lt;p&gt;We always set the user’s clipboard in order to account for when the user updates their clipboard from outside the application. In this case, the clipboard value in the local state may be different from the actual clipboard value, and we want to ensure that our new value gets set, even if our local state value is wrong.&lt;/p&gt;

&lt;p&gt;We always set the React local state in order to trigger any re-render animations or effects, such as a “Clipboard copied!” notification.&lt;/p&gt;

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

&lt;p&gt;This package is &lt;a href="https://www.npmjs.com/package/use-clippy"&gt;available on NPM&lt;/a&gt; and &lt;a href="https://github.com/CharlesStover/use-clippy"&gt;open source on GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you have any questions or great commentary, please leave them in the comments below.&lt;/p&gt;

&lt;p&gt;To read more of my columns, you may follow me on &lt;a href="https://www.linkedin.com/in/charles-stover"&gt;LinkedIn&lt;/a&gt; and &lt;a href="https://twitter.com/CharlesStover"&gt;Twitter&lt;/a&gt;, or &lt;a href="https://charlesstover.com/"&gt;check out my portfolio on CharlesStover.com&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>react</category>
      <category>typescript</category>
      <category>javascript</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Become the junior developer that companies want to hire.</title>
      <dc:creator>Charles Stover</dc:creator>
      <pubDate>Tue, 18 Jun 2019 23:10:56 +0000</pubDate>
      <link>https://forem.com/charlesstover/become-the-junior-developer-that-companies-want-to-hire-39b1</link>
      <guid>https://forem.com/charlesstover/become-the-junior-developer-that-companies-want-to-hire-39b1</guid>
      <description>&lt;h1&gt;
  
  
  Preface 🔰
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Who am I, and why listen to me?
&lt;/h2&gt;

&lt;p&gt;As a self-taught web developer, I struggled to overcome the barriers of entry into the workforce. I had always done well in academia, which resulted in professor affirmation, offers for advanced classes, and offers for scholarships. I naively believed the workforce to behave similarly: that all I had to do was &lt;em&gt;be good at what I did&lt;/em&gt; and the jobs would come to me. If I could pass an interview the way I could pass a test, my encyclopedic knowledge of programming would make finding a job easy.&lt;/p&gt;

&lt;p&gt;That was not the case. Not only did job offers not come flooding into my mailbox, but I could rarely get a response to an application when I reached out to companies directly. What was wrong? I was a good developer. I could solve real world problems. I had created applications and met customer demands. Somehow, I was wholly unprepared for an enterprise setting.&lt;/p&gt;

&lt;p&gt;I doubted my abilities. My ego was crushed. I thought I was intelligent; I thought my projects pushed the envelope; but employers seemed to disagree. They often did not see me as even worth interviewing. The most common feedback I received was that they required a degree. The fact that I had invented applications that generated revenue did not matter. I gave up and pursued other passions, leaving web development as my favorite pastime that it had always been.&lt;/p&gt;

&lt;p&gt;Years later, I decided to pursue web development again after encouragement from my peers. I was still passionate about it. I was good at it. It made me happy. I attempted to re-enter the workforce, knowing from past experience that it would not be easy. I took the act of job searching much more seriously than before. The difference? &lt;em&gt;Humility.&lt;/em&gt; You should &lt;em&gt;know what you don’t know&lt;/em&gt;, and I knew there was something I did not know about web development careers and how they differed from web development as a hobby.&lt;/p&gt;

&lt;p&gt;I spent a lot of time researching how to build a résumé and portfolio, the interview process, and the soft skills of developer careers. I sought résumé and portfolio critique. I did as many practice interviews as I could book. I networked every opportunity. I still research these topics to this day. I take a strong interest in them, as my ignorance of these topics held me back for so long. I am passionate that other developers be prepared to face these issues as well, especially those whom are self-taught, because they are often overlooked in academia and barely existent online.&lt;/p&gt;

&lt;p&gt;Since entering an enterprise setting, I have been involved with as much interview training, sat on as many interview panels, and gathered as much employee feedback as possible. I have applied what I have learned to everyone I have come across who seeks it — from &lt;a href="https://www.reddit.com/user/Charles_Stover"&gt;Reddit&lt;/a&gt; threads to direct &lt;a href="https://linkedin.com/in/charles-stover"&gt;LinkedIn&lt;/a&gt; messages. This is my attempt to publicly document and share this knowledge, in hopes that talented and self-motivated developers receive the fair shot at success they deserve.&lt;/p&gt;

&lt;h1&gt;
  
  
  Education 👨‍🎓👩‍🎓
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--kd5gufrl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/uje1gu5t1keg8j6a2uij.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--kd5gufrl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/uje1gu5t1keg8j6a2uij.png" alt="Education"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Before you can become a junior developer that is in demand, you must first become a &lt;em&gt;junior developer&lt;/em&gt;. This article is not equivalent to an education. This article is meant to be supplemental to an education, be it formal or self-driven.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://amzn.to/2WLr1bG"&gt;Cracking the Coding Interview&lt;/a&gt; by Gayle Laakmann McDowell is another powerful education supplement that I highly recommend. It covers many of the soft skills required by companies and ensures you know the hard skills. You will see it recommended time and time again online, and it is easily worth the $30 investment.&lt;/p&gt;

&lt;p&gt;I encourage anyone to at least read the data structures and algorithms discussed in that book. If you can already solve the problems, implement the data structures, or create the algorithm, then just go to the next one. If you find yourself feeling a bit hazy about the implementation details, I strongly recommend that &lt;em&gt;you write it yourself&lt;/em&gt;. This will add to your portfolio and help solidify the knowledge in your mind. Learning through teaching is a practice that I recommend often. It was my inspiration for &lt;a href="https://medium.com/@Charles_Stover/implementing-quicksort-in-javascript-8044a8e2bf39"&gt;Implementing Quicksort in JavaScript&lt;/a&gt; and the resulting &lt;a href="https://github.com/CharlesStover/quicksort-js"&gt;GitHub repository&lt;/a&gt; and &lt;a href="https://www.npmjs.com/package/@charlesstover/quicksort"&gt;NPM package&lt;/a&gt; for my portfolio.&lt;/p&gt;

&lt;p&gt;You need go a step further than merely knowing what the data structures and algorithms are. Understand the trade-offs between them. When do you choose one over another? Which is more extensible and under what conditions? Which uses less memory or is faster to execute? When would you want to trade memory or efficiency for these other features and why? Knowing the answers to these questions will be very important during your interview process. You will almost certainly be asked to solve a problem that requires a complex data structure. Whichever you choose, you will want to be able to defend. “It’s the first data structure I remembered” does not fly too well on a production application, so it does not fly too well in an interview either.&lt;/p&gt;

&lt;h1&gt;
  
  
  Open Source 📄
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--6LfJPh9L--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/t3un8ratkyj2oibt6qwi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--6LfJPh9L--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/t3un8ratkyj2oibt6qwi.png" alt="Open Source"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It may seem obvious, but a portfolio is meant to be a document of your accomplishments. So document them! &lt;em&gt;Thoroughly.&lt;/em&gt; I mistakenly spent my earliest years creating proprietary software. My server-side code was backed up to several hard drives, and my JavaScript never saw user eyes without first being ran through a minifier. I believed that in order for code to be profitable, it can’t be copied. &lt;em&gt;I was wrong.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I encourage you to open-source as much as possible. Your Quicksort implementation is not doing you any favors on your hard drive. Your intro-to-programming video game may be embarrassingly inefficient, but you are selling it short. These beginner’s projects show:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You wanted to make something and have an interest in programming outside of work.&lt;/li&gt;
&lt;li&gt;You learned to make something and are both willing and capable of learning new technologies as needed.&lt;/li&gt;
&lt;li&gt;You completed a project without giving up. You can see challenges through to the end by overcoming obstacles instead of quitting.&lt;/li&gt;
&lt;li&gt;You &lt;em&gt;did something&lt;/em&gt;. If you do not publish your code, employers will assume that you &lt;em&gt;never wrote it&lt;/em&gt;. It is so much better to write something inefficient than to write nothing at all.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Since open-sourcing my projects, my development career has earned more value than those projects ever offered me on their own. I have received a &lt;a href="https://github.com/CharlesStover/reactn/issues?q=is%3Aissue+is%3Aclosed"&gt;significant amount&lt;/a&gt; of &lt;a href="https://github.com/CharlesStover/use-react-router/issues?q=is%3Aissue+is%3Aclosed"&gt;community feedback&lt;/a&gt; that has allowed me to prioritize what is important to customers and account for use cases and environments I never would have otherwise considered. Bugs that never existed in my environment have arisen in others’. From their reports, I have identified and learned from mistakes in my code designs. Today, I can create components and packages that are extensible to more use cases than just my personal portfolio and projects. These learned concepts and deeper understanding of technologies improve my quality of work.&lt;/p&gt;

&lt;p&gt;For each project, I recommend adding the following to its &lt;code&gt;README.md&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;An actual name. &lt;code&gt;repository-name&lt;/code&gt; is nice and automated, but try to give it a description that differentiates you from other candidates. Every candidate has a “TODO App” and “Shopping List.” Why is yours better? Try “React TODO App” or “MongoDB Shopping List.”&lt;/li&gt;
&lt;li&gt;An actual description. “TODO App” can mean a lot of things. It is obvious to you, because you made it. What &lt;a href="https://en.wikipedia.org/wiki/Create,_read,_update_and_delete"&gt;CRUD operations&lt;/a&gt; does it support? Does it use server-side code? Who is the target audience? What problem are you solving and how? For example, my &lt;a href="https://github.com/CharlesStover/shopping-list"&gt;Shopping List&lt;/a&gt; application “was created for my father, who needed a printable shopping list for his home care aides. To support his declining memory, the application keeps track of past items so that they may be re-added with ease.” I have put the customer first, identified a problem, and executed on a solution.&lt;/li&gt;
&lt;li&gt;The tech stack used. HTML, JavaScript, React, PHP, SQL, Docker? Let people know what you have experience using. Even if your project is not the cleanest code or optimal implementation, you have demonstrated that you understand these technologies at least in concept. You know what problems they solve, and that’s the largest hurdle. Perfecting their use can be learned on the job.&lt;/li&gt;
&lt;li&gt;Nobody, and I mean nobody, is going to clone your repository, install it, then run it locally just to see your work. Companies are often flooded with candidates (whether or not they are good candidates). They will just move on to the next candidate instead. At this point in time, to the company, you are statistically likely to be average. Their time is better spent researching another candidate than wasting time or muddying their machine. If your project is front end, consider deploying it to &lt;a href="https://pages.github.com/"&gt;GitHub Pages&lt;/a&gt;. If your project is not front end, consider adding screenshots of any GUI, linking to a live demonstration of any API, or documenting example inputs and outputs.&lt;/li&gt;
&lt;li&gt;Document your API, if there is one. This is good experience and practice for when you are creating highly used, production-facing APIs in an enterprise setting. Companies want good documentation, even for APIs that are only used internally. Every time an internal customer references the documentation, there is one less support ticket to answer and one more free hour for a developer to implement new features instead of support existing ones. When the creator of an API leaves the company, how quickly can their replacement support the service they have inherited? Many companies have been burned by this before, and they know that good documentation is indicative of team-thinking.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Networking 🌐
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--e8unapFl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/zbi4i7q1t8ntec64klut.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--e8unapFl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/zbi4i7q1t8ntec64klut.jpg" alt="Wiki Meetup in Thailand at Central Embassy by Mohammed Galib Hasan (CC BY-SA 4.0, unmodified)"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you want to &lt;em&gt;stand out&lt;/em&gt;, then you first need to &lt;em&gt;stand&lt;/em&gt;. Not only should recruiters be able to find you, they should be impressed by what they see. Get your name out there for good reasons.&lt;/p&gt;

&lt;h2&gt;
  
  
  LinkedIn
&lt;/h2&gt;

&lt;p&gt;Under your &lt;a href="https://www.linkedin.com/jobs/career-interests/"&gt;Career Interests&lt;/a&gt;, let recruiters know you are open. Reply to every recruiter, whether or not you want the job. Practice your professional communication skills. Practice putting complex social and career situations into words that are articulate and unoffensive. These skills will translate both into an interview setting and the workplace. Sometimes, you know what you want, but you do not quite know how to say it. Later, when you are interviewing, it will be good to be able to articulate professionally what it is that you want from the job — and that is the best way to get it.&lt;/p&gt;

&lt;p&gt;Practice declining jobs in which you are not interested without burning bridges. That recruiter may reach out to you in the future with a better opportunity more tailored to your interests. Similarly, job offers that you do not accept today may become desirable in the future. Finally, when you leave your first job for your second, your experience in rejecting your current company &lt;em&gt;without burning bridges&lt;/em&gt; will help you get that professional recommendation.&lt;/p&gt;

&lt;p&gt;Squeeze recruiters for information. Find out what is in demand. For what skills are they looking? If they inform you that you are not the right fit for a position, ask them why. What are you lacking? What should you study? If you re-apply in some number of months, what do they want to see improved that could land you the position? Drop your pride, up your humility, and understand that employers want an employee that can &lt;em&gt;learn&lt;/em&gt;, not one who thinks they know everything already. A candidate telling me that they will be back and more ready than ever is a very positive sign. It shows dedication, it shows an eagerness to learn, and if they come back having corrected their faults, it shows an ability to &lt;em&gt;succeed&lt;/em&gt; at their goals.&lt;/p&gt;

&lt;p&gt;Learn your worth. No matter the recruiter or the position, &lt;em&gt;what is the compensation&lt;/em&gt;? What does a front end engineer make in Seattle? What does a PHP developer make in Indiana? What does a React Native developer make in India? (Do note that I included a location in each of these. The greatest determinant for compensation is location!) When your first job offer inevitably asks what you want as far as compensation, &lt;em&gt;you will know what you are worth&lt;/em&gt;. Do not be afraid to high-ball. Once they have decided that they want you, they will not just reject you for asking too much. They will counter with their max. This is better than low-balling yourself and making closer to minimum wage than your worth. This is a great way to lose motivation, feel underappreciated, and quickly burn out during your job.&lt;/p&gt;

&lt;p&gt;Link to your LinkedIn profile liberally. Your projects outside of LinkedIn should include links to LinkedIn. Recruiters who are impressed by your work need a way to contact you. Developers who are impressed by your work may be willing to give you a job recommendation. For example, I end every Medium article with “Follow me on &lt;a href="https://www.linkedin.com/in/charles-stover/"&gt;LinkedIn&lt;/a&gt;.” At this time, these link shares have resulted in 300 connections.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Stand&lt;/em&gt;, and allow yourself to be found.&lt;/p&gt;

&lt;h2&gt;
  
  
  Twitter
&lt;/h2&gt;

&lt;p&gt;Keep your Twitter account professional. It is okay to have personal tweets, but do not have anything controversial. Build a following by constantly tweeting what you have accomplished, and share your Twitter profile on your projects to build a following. For example, I end every Medium article with “Follow me on &lt;a href="https://twitter.com/CharlesStover"&gt;Twitter&lt;/a&gt;.” At this time, these link shares have resulted in 300 followers.&lt;/p&gt;

&lt;p&gt;Twitter is free marketing. I have never made a social tweet. I maintain a strictly business Twitter account. If I post what I have made, people will see it, interact with it, provide feedback, and share it. Related hashtags, such as the tech stack, can be used to encourage bots to auto-retweet you for a wider audience.&lt;/p&gt;

&lt;h1&gt;
  
  
  Résumé 💼
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--fTk8q6iV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/vf7gy9hgwutcxdtvtowl.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--fTk8q6iV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/vf7gy9hgwutcxdtvtowl.jpg" alt="Photo by Staff Sgt. Kayla Rorick"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The million dollar questions are, “How do you stand out from every other equally-education recent college graduate?” and “How do you show that your self-taught education is equal to your accredited competitors?”&lt;/p&gt;

&lt;p&gt;First things first, actually write your résumé! Be sure to keep your portfolio and résumé in sync with your LinkedIn. This helps recruiters find you and know what tech stacks with which you are familiar.&lt;/p&gt;

&lt;p&gt;Keep your résumé to one page. If you think you need more than that because you have accomplished so much, &lt;em&gt;you are wrong&lt;/em&gt;. For reference, my 17 years of experience is still &lt;a href="https://charlesstover.com/resume/2019-05/charles-stover-resume.pdf"&gt;a one page résumé&lt;/a&gt;. It is more likely that you are including information that should not be in a résumé. Remember that a résumé gets you to the interview. The fine details come up in the interview itself.&lt;/p&gt;

&lt;p&gt;LinkedIn often has promotions with free courses on their &lt;a href="https://www.linkedin.com/learning/"&gt;LinkedIn Learning&lt;/a&gt; platform. Completing these courses adds a Certification entry to your LinkedIn profile — an easy and fun way to stand out.&lt;/p&gt;

&lt;p&gt;Tailor your résumé to the job to which you are applying. Your education, experience, interests, and goals can all be conversation pieces during the interview. Know how they relate to the job. What formal training have you had in the field? Note college courses or online training that were particularly relevant. What past work applies specifically to this job? Remove unrelated projects. An employer seeking a front end engineer is not going to ask you about the time you coded a &lt;a href="https://en.wikipedia.org/wiki/Caesar_cipher"&gt;Caesar cipher&lt;/a&gt; in assembly. Any time they spend reading about it is mental fatigue that turns them off to you as a candidate. Any time they spend discussing it with you is likely time wasted. They will not have learned if you are a correct fit for the job. That time is better spent informing them of your strengths in the field.&lt;/p&gt;

&lt;p&gt;Do not list items on your résumé that you cannot defend. You may think you need to lie to land an interview, but you do not. Part of the interview process is specifically tailored to weed out liars. You achieve nothing more than wasting everyone’s time, including your own. You will be grilled on technologies you list and asked to give specifics about past projects. It will be apparent if you are not familiar with these technologies or supposed projects. It does not look good to claim to have worked with NPM and Travis CI but be unable to define them, what problems they solved, or how these tools solved those problems. Even vague answers can be red flags. You know that NPM managed your Node packages, but you do not know what packages, why you would want this tool on your project, or the commands you used. These are great reasons to explicitly not hire you. It would realistically be a better choice to hire a candidate who has no experience with NPM than one who supposedly does have experience but cannot answer the above. The inexperienced candidate may be able to learn. The lying candidate has demonstrated that they are incapable of learning.&lt;/p&gt;

&lt;p&gt;I do not say the above to make you fear of listing a technology on your résumé. I say the above to emphasize how many candidates lie, how employers have come to expect this, and to encourage you not to waste your time lying also. If you honestly have experience with a technology, do not be afraid to list or discuss it. If you do not know the answer to a question, admit it and explain why. “We used NPM to install packages, but the only one I know is &lt;code&gt;npm install&lt;/code&gt;. The CI/CD pipeline ran the rest automatically, so I am unfamiliar with them.” You have demonstrated that you do understand what the tool is and what the tool solves. You have not demonstrated that you are incapable of learning. If I heard this answer, I would think you are perfectly capable of learning NPM better on the job. This is in stark contrast to the lying candidate who claims to have used a tool but cannot offer specifics about when, where, or why.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Sell yourself.&lt;/em&gt; Don’t &lt;em&gt;sell yourself short&lt;/em&gt;. Be proud of what you have accomplished and be confident in your verbiage. You did not “make a small website for a friend.” You “exceeded a customer’s expectations by delivering a accessibility-compliant single-page-application and maintain it through an Issues tracker and a CI/CD pipeline.” Employers do not want to make small websites for your friends. They want to make SPAs, perform long-term maintenance, track issues, and automate deployment. Your description of your project should not be “I made a tic-tac-toe clone in the browser,” but “A React application that implements Flux architecture through Redux, supporting keyboard navigation and performing animations with CSS.” Remember to tailor the résumé to the job and describe your projects with marketable terms.&lt;/p&gt;

&lt;h1&gt;
  
  
  Mentality 🧠
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--cD48xEBB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/4sj8eqxptk45hbehr4ob.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--cD48xEBB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/4sj8eqxptk45hbehr4ob.jpg" alt="Mentality"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Know yourself.
&lt;/h2&gt;

&lt;p&gt;Why are you interviewing for this position? What are your short and long term goals, and how does this position help you reach them?&lt;/p&gt;

&lt;p&gt;For my last interview, my answers to these questions were: I want a higher skill ceiling than my previous job. I want to be challenged to learn new technologies and better myself. I feel like I have plateaued at my previous place of employment, and I have an intrinsic motivation to become the best developer that I can be.&lt;/p&gt;

&lt;p&gt;Employers want to know you are a right fit for them. If you just want money, you are a right fit anywhere — meaning there is no guarantee you will remain loyal when a competitor offers more. They do not want to invest in you if this is the case. For my last career shift, I would have been willing to take a pay cut, because it meant I could achieve greater things, and that is what mattered to me.&lt;/p&gt;

&lt;h2&gt;
  
  
  Interviews should not be scary.
&lt;/h2&gt;

&lt;p&gt;You should have the mentality that every interview is good for you. Much the way you can squeeze a recruiter for information, you can do the same with an interview. Determine what tech stacks their company uses, what skills are in demand, and why they are not interested. Some interviewers are unable to give you this information without first passing it through to HR, so be sure to follow up with HR after the interview. Use this information to better yourself between interviews.&lt;/p&gt;

&lt;p&gt;Interview places that you “know” you will not accept. I put know in quotes, because I have known someone to accept a job offer after following this advice, interviewing with no intention of accepting, finding out they actually loved the company, and accepting the offer. This is my only morally-ambiguous piece of advice. Practice interviewing at places in which you do not have an interest. Squeeze them for the same information — what is their tech stack, what skills do they value, in what areas can you improve, and if you receive a job offer, what is your worth? These practice interviews will allow you to better communicate your soft skills with less anxiety, and it will show when you take on an interview for a job that you really want.&lt;/p&gt;

&lt;p&gt;Treat your interview like it your first day on the job. This should help decrease your anxiety and feel less pressure of being judged. Interact with the interviewer as if they are your coworker. The entire point of an interview is for the interviewer to determine how you would behave on the job. When they ask you questions, it is not because this is a test, and you have to achieve 90% of higher to pass. It is because they want to see your thought process when you are given real world problems to solve. This thought process is not just getting a right or wrong answer. How many edge cases did you consider? Could you discern which did or did not apply to the customer in this use case? Did you take extra steps when solving the problem to make your code extensible to possible future modification, despite it not being a part of the current feature request? Can you communicate difficult technical concepts, data structures, algorithms, and their trade offs? Do you know when to ask for help, or do you think you know everything? These are potential areas in which the interviewer is taking notes, because these are the things you will work on in a team. Engage your interviewer. Talk to them. Ask them questions. Describe your thought process. Think out loud. Seeing them as a coworker really helps aid in this task.&lt;/p&gt;

&lt;h1&gt;
  
  
  Interview Preparation 👨‍💼👩‍💼
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--4_rDjF2M--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/521rm1xmbkgvfnm4al29.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--4_rDjF2M--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/521rm1xmbkgvfnm4al29.jpg" alt="Interview Preparation"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To prepare for your interview, make sure that you are intimately familiar with the &lt;a href="https://en.wikipedia.org/wiki/Situation,_task,_action,_result"&gt;S.T.A.R. format&lt;/a&gt;. When your interviewer asks you to describe an event, try your best to answer with S.T.A.R. This ensures you provide the information for which your interviewer is probing and that there is no miscommunication between the two of you. If your misinterpreted the question, it should become clear by the situation or task that you are answering the wrong question. If you are answering the right question, the interviewer may be looking for relevant experience (situation), problem identification or communication skills (task), problem-solving or technical skills (action), or ability to deliver results, compromise, or learn from mistakes (result). By answering with S.T.A.R., your bases are covered, and strong communication is achieved.&lt;/p&gt;

&lt;h2&gt;
  
  
  Create a list of your most impressive projects.
&lt;/h2&gt;

&lt;p&gt;Impressive is subjective, but here I mean the projects that were the most extensive or unique. You worked on a team, you worked with clients, you worked with a manager, you received notable amounts of community feedback, it went viral, or you accomplished something that took weeks not hours. Prepare to reference your most impressive projects during behavioral questions. Unlike the quantitative, encyclopedic knowledge of programming, sometimes you can draw a blank when asked qualitative questions. You have so much experience writing for loops and traversing arrays that it comes second nature when asked to do so. Unfortunately, when asked to “name a time you had a disagreement with a superior,” you might not have an example at the ready. Your mind can go blank as you try to process this question.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;What if I’ve never had a disagreement? If I say I have not, do I sound inexperienced or like I’m lying? And if I have, will it sound like I am difficult to work with or oppositional? What counts as a disagreement? Who counts as a superior? I have little to no work history! How am I supposed to have disagreed with a superior?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Do be aware that behavioral questions do not typically mean &lt;em&gt;on the job&lt;/em&gt;. In the previous question, a superior may be a professor or a mentor. A disagreement does not need to be a heated argument, but could be different opinions on implementation details. You can make the question as generic as it needs to be to have an answer, and that’s why creating a list of your most impressive projects up front can be beneficial.&lt;/p&gt;

&lt;p&gt;I highly recommend reading through &lt;a href="https://www.amazon.jobs/en/principles"&gt;Amazon’s Leadership Principles&lt;/a&gt;. These are some of the most well-rounded, all-encompassing, and rigorously tested behavioral skills on the Internet. You would be hard-pressed to find a soft skill that is both important and not on this list. For each leadership principle, I recommend associating it with one of your impressive projects. Add new projects or situations as needed.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Project A — I &lt;em&gt;learned&lt;/em&gt; something new.&lt;/li&gt;
&lt;li&gt;Project B — I &lt;em&gt;invented&lt;/em&gt; a tool to aid the development process.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You may absolutely assign multiple principles to a single project, but I strongly recommend that you have a project or situation for each principle. If you find yourself unable to associate some, think harder. Try removing the job or development aspect from the association. A time you were &lt;em&gt;frugal&lt;/em&gt; may have just been in your day-to-day life, where you have managed to cut expenses in order to prioritize paying off your student loans and therefore decreasing your accumulated interest.&lt;/p&gt;

&lt;p&gt;Once you have associated each leadership principle with a project or situation, clean up your list. Remove projects or situations that are not associated with any soft skills. You should be left with just a list of your &lt;em&gt;actual&lt;/em&gt; most impressive projects.&lt;/p&gt;

&lt;p&gt;Bring this list with you to interview. When you are asked a behavioral question, if needed, read over this list to jog your memory of a time it applied. Do not write the soft skills next to the projects. The point of this list is to be memory-jarring. You should be able to skim it in a few seconds in response to a question, not spend several minutes reading a page of summaries before you answer. The combination of the location (project) and event (question) should be enough to quickly jog your memory of any relevant experience you may have.&lt;/p&gt;

&lt;p&gt;It may feel odd to have to look at notes of your own life story in response to a question about yourself, but do not worry. Interviewers are aware of the impact of nervousness during the interview process, and I assure you no one will mind that you took notes about your own soft skills. People struggle with these questions more than any others, so your ability to answer at all will put you ahead of the curve.&lt;/p&gt;

&lt;h2&gt;
  
  
  Bring data.
&lt;/h2&gt;

&lt;p&gt;Numbers are the universal language. They remove ambiguity and drive business decisions. If you have data to accommodate your claims, bring it. By what percentage did you boost productivity or revenue? How much money did you generate? How much time did you save? If you only have qualitative results, they are better than nothing. Measuring your efficiency not only drives home the reality of your value, but it shows a mindset of valuing analytical data that indicates that you will do the same on the job.&lt;/p&gt;

&lt;p&gt;For example, some data I collected prior to my last interview:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I reduced network traffic by 30% (gzipped) to 60% (non-gzipped) by implementing an opt-in (backwards compatible) compression algorithm on the API. This was not a complicated algorithm. I never had formal training in compression or data. I simply noticed that network traffic was being wasted downloading the same property names repeatedly. A quick Google search shows that &lt;a href="https://stackoverflow.com/questions/37988451/convert-array-of-objects-to-an-object-of-arrays"&gt;I was not the only one to seek this data conversion&lt;/a&gt;. I measured the packet sizes with and without this change, and viola — data.&lt;/li&gt;
&lt;li&gt;I simplified an existing internal testing framework for a project. This resulted in the development time for end-to-end testing decreasing from 3 days per path to just 1. This wasn’t rocket science. I was annoyed by how difficult the existing framework was to use, so I turned common commands into re-usable function calls. When the team responded that it was much nicer to use, I documented the change in development time.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Be confident.
&lt;/h2&gt;

&lt;p&gt;Confidence is important. Identify your insecurities and practice addressing them. If your interviewer probes these aspects of you and your achievements, you do not want to validate their concerns by lacking answers.&lt;/p&gt;

&lt;p&gt;Do you lack a degree? Why? You thought it was the right choice for you to make. Why? You decided that you could achieve academic equality to a college graduate. Why? Leave your fear of judgment behind and take pride in your decisions. If you cannot be confident that your choices thus far are the right ones, how can you be trusted to make the right choices for the company?&lt;/p&gt;

&lt;p&gt;I lack a degree in Computer Science. It was my biggest insecurity in my first attempt to enter the workforce. Now, I am outspoken against learning software development through college curriculums. I am confident that it was the correct decision for me. It would have cost me too much money and provided too little benefit. I learned faster on my own than in a classroom. I have worked with developers in open-source, in person, and engaged myself in as many developer communities as I can find. I have proven that I can comprehend and discuss complex topics, so I am confident that a college education would not improve myself as a developer. I can articulate that sentiment to an interviewer.&lt;/p&gt;

&lt;p&gt;Once you understand yourself, practice articulating it. Practice by yourself, putting your thoughts into words. There is a lot of emotion behind anxiety, insecurity, and fear of judgment. It can be difficult to find the right words to label emotionally-charged aspects of your life. &lt;em&gt;Practice, practice, practice.&lt;/em&gt; Once you believe you have adequately described your biggest challenges, practice with friends and relatives. Then, practice with mentors and coworkers. &lt;em&gt;Practice, practice, practice.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Seek &lt;em&gt;honest&lt;/em&gt; feedback. If your goal is to improve or land a job, you do not want your ego stroked. You want constructive &lt;em&gt;criticism&lt;/em&gt;. Make sure those close to you know that they should not be afraid of hurting your ego, and make sure your ego is not hurt by opportunities for self-improvement.&lt;/p&gt;

&lt;h2&gt;
  
  
  In the end…
&lt;/h2&gt;

&lt;p&gt;When the interview has come to a close, your interviewer will often give you an opportunity to ask questions. Do ask questions. This shows that you have an actual interest in the company and are not just here for a paycheck. Do not ask about pay, vacation time, time off, or anything else that insinuates that you care more about money than your career. Do ask about company culture, opportunities for growth, team dynamics, tech stacks, and making sure you are a good fit for each other. You are interviewing the company just as much as the company is interviewing you. They do not want to put you in an environment where you will not be happy — that’s the fastest way to have an employee quit. Identify what is important to you, and ask how questions related to your short and long term goals.&lt;/p&gt;

&lt;p&gt;End the interview with a closing statement. It does not feel as natural as it should, but after you have asked your questions, segue to a closing statement. “I don’t have any further questions, but I do have one comment.” This is your opportunity to describe your best qualities and what you can bring to the team. Instead of the interviewer leaving the interview fixated on your minor imperfections, have them leave with a positive thought. If your greatest qualities did not come up naturally during conversation, now is your opportunity to address them. During an interview, the bottom of my notes reference a few of what I consider to be my strongest qualities. If they came up already, I ignore them; if they did not come up, I bring them up now.&lt;/p&gt;

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

&lt;p&gt;If you have any questions or relevant great advice, please leave them in the comments section.&lt;/p&gt;

&lt;p&gt;To read more of my articles or follow my works, you may connect with me on &lt;a href="https://www.linkedin.com/in/charles-stover"&gt;LinkedIn&lt;/a&gt; and &lt;a href="https://twitter.com/CharlesStover"&gt;Twitter&lt;/a&gt;. It’s quick, it’s easy, and it’s free!&lt;/p&gt;

&lt;p&gt;You can also &lt;a href="https://charlesstover.com/"&gt;check out my portfolio on CharlesStover.com&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>career</category>
      <category>beginners</category>
      <category>webdev</category>
      <category>discuss</category>
    </item>
    <item>
      <title>Implementing Quicksort in JavaScript</title>
      <dc:creator>Charles Stover</dc:creator>
      <pubDate>Wed, 05 Jun 2019 23:53:19 +0000</pubDate>
      <link>https://forem.com/charlesstover/implementing-quicksort-in-javascript-57k4</link>
      <guid>https://forem.com/charlesstover/implementing-quicksort-in-javascript-57k4</guid>
      <description>&lt;p&gt;Quicksort is one of the most efficient methods for sorting an array in computer science. For a thorough breakdown, &lt;a href="https://en.wikipedia.org/wiki/Quicksort" rel="noopener noreferrer"&gt;it has its own Wikipedia article&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This article will cover implementing quicksort in JavaScript. Quicksort is not built in to JavaScript. Due to the &lt;code&gt;sort&lt;/code&gt; method on the Array prototype, sorting is rarely questioned or optimized in the language. Despite that, Quicksort is still an important algorithm to at least &lt;em&gt;comprehend&lt;/em&gt;, whether or not you use it.&lt;/p&gt;

&lt;h1&gt;
  
  
  How does it work? 🤔
&lt;/h1&gt;

&lt;p&gt;Quicksort works by picking an element from the array and denoting it as the “pivot.” All other elements in the array are split into two categories — they are either less than or greater than this pivot element.&lt;/p&gt;

&lt;p&gt;Each of the two resulting arrays (array of values less-than-the-pivot and array of values greater-than-the-pivot) is then put through that very same algorithm. A pivot is chosen and all other values are separated into two arrays of less-than and greater-than values.&lt;/p&gt;

&lt;p&gt;Eventually, a sub-array will contain a single value or no value at all, as there will be no more values with which to compare it. The rest of the values were all denoted to be “pivots” at some previous point and did not trickle down to this lowest sub-array. At that point, the values will be sorted, as all values have now been declared as less than or greater than all other values in the array.&lt;/p&gt;

&lt;h1&gt;
  
  
  How do we implement it? 💡
&lt;/h1&gt;

&lt;p&gt;Since the Array prototype method &lt;code&gt;sort&lt;/code&gt; uses its own sorting algorithm, we cannot use it for implementing quicksort. We must create a function that receives the array-to-sort as a parameter and return the sorted-array.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;quickSort&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;unsortedArray&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;sortedArray&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;TODO&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;unsortedArray&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;sortedArray&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;Since the “value” of the item in the array may not be immediately obvious, we should offer an optional parameter for the comparator. Sorting strings or numbers is built in to JavaScript, but sorting objects isn’t. We may want to sort a collection of user objects (&lt;code&gt;{ name: 'Charles', age: 21 }&lt;/code&gt;) by age.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;defaultComparator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;b&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="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;quickSort&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;unsortedArray&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;comparator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;defaultComparator&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;sortedArray&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;TODO&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;unsortedArray&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;sortedArray&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;Since the number of times we can divide this array into less-than/greater-than halves can vary towards infinity, we want to recursively define our logic so that we aren’t repeating our code (“pick a pivot, split, repeat”).&lt;/p&gt;

&lt;p&gt;You may use any index as the pivot location: first, middle, last, random. Assuming randomly-sorted data, the location of the pivot won’t impact the time complexity. I will be using the last index, because that is what Wikipedia uses in its demonstration graphic, and it is nice to have a visual to coincide with the code.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fizvdb1hgadjj43arjy9w.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fizvdb1hgadjj43arjy9w.gif"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The array in front of the pivot is split into two: less than the pivot at the front, greater than the pivot at the end. Finally, the pivot itself is moved between the two sub-arrays, then the sub-arrays are sorted by the same quicksort algorithm.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;quickSort&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;unsortedArray&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;comparator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;defaultComparator&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;// Create a sortable array to return.&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;sortedArray&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[...&lt;/span&gt;&lt;span class="nx"&gt;unsortedArray&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

  &lt;span class="c1"&gt;// Recursively sort sub-arrays.&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;recursiveSort&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;start&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;end&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;// If this sub-array is empty, it's sorted.&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;end&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;start&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;pivotValue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;sortedArray&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;end&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;splitIndex&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;start&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="c1"&gt;// Sort the entire array.&lt;/span&gt;
  &lt;span class="nf"&gt;recursiveSort&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;unsortedArray&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;sortedArray&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 create &lt;code&gt;sortedArray&lt;/code&gt; as a new array so as not to mutate the original array. This isn’t necessarily required, but it’s good practice.&lt;/p&gt;

&lt;p&gt;We create &lt;code&gt;recursiveSort&lt;/code&gt; as the recursive function that will take a subarray (from start index to end index) and quicksort it, mutating the &lt;code&gt;sortedArray&lt;/code&gt; along the way. The entire array is the first array to be passed to this recursive function.&lt;/p&gt;

&lt;p&gt;Finally, the sorted array is returned.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;recursiveSort&lt;/code&gt; function has a &lt;code&gt;pivotValue&lt;/code&gt; variable to denote the value of our pivot and a &lt;code&gt;splitIndex&lt;/code&gt; variable to denote the index delimiting the less-than and greater-than arrays. Conceptually, all less-than values will be at indices less than &lt;code&gt;splitIndex&lt;/code&gt; and all greater-than values will be at indices greater than &lt;code&gt;splitIndex&lt;/code&gt;. &lt;code&gt;splitIndex&lt;/code&gt; is initialized to the start of the subarray, but as we discover values less than the pivot value, we will adjust &lt;code&gt;splitIndex&lt;/code&gt; accordingly.&lt;/p&gt;

&lt;p&gt;We’ll loop through all the non-pivot values, moving the ones less than the pivot value to before the start index.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;quickSort&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;unsortedArray&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;comparator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;defaultComparator&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;// Create a sortable array to return.&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;sortedArray&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;unsortedArray&lt;/span&gt; &lt;span class="p"&gt;];&lt;/span&gt;

  &lt;span class="c1"&gt;// Recursively sort sub-arrays.&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;recursiveSort&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;start&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;end&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;// If this sub-array is empty, it's sorted.&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;end&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;start&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;pivotValue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;sortedArray&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;end&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;splitIndex&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;start&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;start&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;end&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;sort&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;comparator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;sortedArray&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="nx"&gt;pivotValue&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

      &lt;span class="c1"&gt;// This value is less than the pivot value.&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;sort&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

        &lt;span class="c1"&gt;// If the element just to the right of the split index,&lt;/span&gt;
        &lt;span class="c1"&gt;//   isn't this element, swap them.&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;splitIndex&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;temp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;sortedArray&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;splitIndex&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
          &lt;span class="nx"&gt;sortedArray&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;splitIndex&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;sortedArray&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
          &lt;span class="nx"&gt;sortedArray&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;temp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="c1"&gt;// Move the split index to the right by one,&lt;/span&gt;
        &lt;span class="c1"&gt;//   denoting an increase in the less-than sub-array size.&lt;/span&gt;
        &lt;span class="nx"&gt;splitIndex&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="c1"&gt;// Leave values that are greater than or equal to&lt;/span&gt;
      &lt;span class="c1"&gt;//   the pivot value where they are.&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// Move the pivot value to between the split.&lt;/span&gt;
    &lt;span class="nx"&gt;sortedArray&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;end&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;sortedArray&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;splitIndex&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="nx"&gt;sortedArray&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;splitIndex&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;pivotValue&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// Recursively sort the less-than and greater-than arrays.&lt;/span&gt;
    &lt;span class="nf"&gt;recursiveSort&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;start&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;splitIndex&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nf"&gt;recursiveSort&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;splitIndex&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;end&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="c1"&gt;// Sort the entire array.&lt;/span&gt;
  &lt;span class="nf"&gt;recursiveSort&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;unsortedArray&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;sortedArray&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 move all values less than the pivot value to &lt;code&gt;splitIndex&lt;/code&gt; and all leave all other values where they are (by default, greater than the &lt;code&gt;splitIndex&lt;/code&gt;, since the split index starts at the beginning of the sub-array).&lt;/p&gt;

&lt;p&gt;Once the sub-array has been reordered, we move the pivot itself to the split, since we know it is located &lt;em&gt;between&lt;/em&gt; all less-than and greater-than-or-equal-to values.&lt;/p&gt;

&lt;p&gt;All values to the left (from &lt;code&gt;start&lt;/code&gt; to &lt;code&gt;splitIndex - 1&lt;/code&gt;) get recursively sorted and all values to the right (from &lt;code&gt;splitIndex + 1&lt;/code&gt; to &lt;code&gt;end&lt;/code&gt;) get recursively sorted. &lt;code&gt;splitIndex&lt;/code&gt; itself is now the pivot value, which no longer needs to be sorted.&lt;/p&gt;

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

&lt;p&gt;You can find the code in this article published in &lt;em&gt;TypeScript&lt;/em&gt; &lt;a href="https://github.com/CharlesStover/quicksort-js" rel="noopener noreferrer"&gt;on GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;You may also add this code to your projects &lt;a href="https://www.npmjs.com/package/@charlesstover/quicksort" rel="noopener noreferrer"&gt;from NPM&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you liked this article, feel free to give it a heart or a unicorn. It’s quick, it’s easy, and it’s free! If you have any questions or relevant insight, please leave a comment.&lt;/p&gt;

&lt;p&gt;To read more of my columns or contact me, you can find me on &lt;a href="https://www.linkedin.com/in/charles-stover" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;, &lt;a href="https://medium.com/@Charles_Stover" rel="noopener noreferrer"&gt;Medium&lt;/a&gt;, and &lt;a href="https://twitter.com/CharlesStover" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt;, or &lt;a href="https://charlesstover.com/" rel="noopener noreferrer"&gt;check out my portfolio on CharlesStover.com&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>algorithms</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Variable length currying in JavaScript</title>
      <dc:creator>Charles Stover</dc:creator>
      <pubDate>Wed, 05 Jun 2019 23:44:47 +0000</pubDate>
      <link>https://forem.com/charlesstover/variable-length-currying-in-javascript-1g5m</link>
      <guid>https://forem.com/charlesstover/variable-length-currying-in-javascript-1g5m</guid>
      <description>&lt;p&gt;This is an interesting programming challenge that reddit user &lt;code&gt;i7_leaf&lt;/code&gt; claims to have received as &lt;a href="https://www.reddit.com/r/javascript/comments/9vxdkx/was_asked_this_js_interview_question_is_this_even/"&gt;an interview question&lt;/a&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  Preface ⭐
&lt;/h1&gt;

&lt;p&gt;There is one key difference between the original question and what I will cover in this article. The interview question asked the candidate to write a function that executes as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;addSubtract&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;          &lt;span class="c1"&gt;// 1 + 2 - 3             = 0&lt;/span&gt;
&lt;span class="nx"&gt;addSubtract&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 1 + 2 - 3 + 4 - 5 + 6 = 5&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It is worth noting that this curried function does not end in any sort of delimiter, e.g. a terminating method &lt;code&gt;.execute()&lt;/code&gt; or empty parameter &lt;code&gt;()&lt;/code&gt;. What makes this challenge both difficult and interesting is the lack of signal that “this is the last digit in the sequence.”&lt;/p&gt;

&lt;p&gt;I agree with the majority of comments in the discussion thread that the interviewer did not mean to ask this question &lt;em&gt;per se&lt;/em&gt;. As postulated, this function cannot exist. It is impossible for &lt;code&gt;addSubtract(1)(2)(3)&lt;/code&gt; to both be a primitive (the number 0 in the first example) and a function (that accepts 4 as a parameter in the second example).&lt;/p&gt;

&lt;p&gt;That said, this is &lt;em&gt;conceptually&lt;/em&gt; possible with a very slight tweak. While the following two statements &lt;em&gt;cannot both&lt;/em&gt; be true, the third statement &lt;em&gt;can&lt;/em&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// This cannot be true with the following statement.&lt;/span&gt;
&lt;span class="nx"&gt;addSubtract&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// This cannot be true with the preceding statement.&lt;/span&gt;
&lt;span class="nx"&gt;addSubtract&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// This can be true:&lt;/span&gt;
&lt;span class="nx"&gt;addSubtract&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;addSubtract&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// These can be true too:&lt;/span&gt;
&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="nx"&gt;addSubtract&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="nx"&gt;addSubtract&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I believe the interviewer was actually testing the candidate’s ability to write a curried function that alternates add and subtract operations, but innocently did not realize the two function examples were mutually exclusive. The scenario in the third statement is such an obscure functionality of JavaScript that I do not support its use as an interview question. It’s a “think outside the box” solution, but not a &lt;em&gt;practical&lt;/em&gt; one.&lt;/p&gt;

&lt;h1&gt;
  
  
  How does it work? 🤔
&lt;/h1&gt;

&lt;p&gt;Any object can be type cast to a string or number using built-in methods.&lt;/p&gt;

&lt;p&gt;The use of &lt;code&gt;+&lt;/code&gt; in the third example attempts to type cast both sides of the argument to a &lt;code&gt;Number&lt;/code&gt; type. If there is no way to type cast to a &lt;code&gt;Number&lt;/code&gt; type, it will attempt to typecast to a &lt;code&gt;String&lt;/code&gt; type (the same way &lt;code&gt;'Hello ' + 123 === 'Hello 123'&lt;/code&gt;). It is because of our ability to explicitly define how to type cast an object that we are able to solve the problem of &lt;code&gt;addSubtract(1)(2)(3) + addSubtract(1)(2)(3)(4)(5)(6)&lt;/code&gt;, and it is because of JavaScript lack of type casting when calling the object by itself that it cannot know that &lt;code&gt;addSubtract(1)(2)(3)&lt;/code&gt; is the primitive &lt;code&gt;0&lt;/code&gt;. It is, in fact, not the primitive number &lt;code&gt;0&lt;/code&gt;. It is a function, which is why we can both treat it as an object able to be type cast and call it as a function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;addSubtract&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// function&lt;/span&gt;
&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;    &lt;span class="c1"&gt;// type cast to 0&lt;/span&gt;
&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// type cast to 4&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When treating an object (or function) as a number, the &lt;code&gt;valueOf&lt;/code&gt; method of that object will be called, the return value of which is what is used for the numerical operation. When treating an object as a string, the &lt;code&gt;toString&lt;/code&gt; method of that object will be called.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;myStrObject&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Str&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;My object is &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;myStrObject&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 'My object is Str'&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;myStrObject&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;297&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;             &lt;span class="c1"&gt;// 'Str297'&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;myNumObject&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;valueOf&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;123&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;My object is &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;myNumObject&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 'My object is 123'&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;myNumObject&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;297&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;             &lt;span class="c1"&gt;// 420&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Let’s curry 🍛
&lt;/h1&gt;

&lt;p&gt;That’s really all the introduction you need to solve this problem, so I’ll provide the solution.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Given an array of numbers, if the index is even, add.&lt;/span&gt;
&lt;span class="c1"&gt;//   If the index is odd, subtract.&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;addSubtractReducer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;total&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;index&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;index&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt;
    &lt;span class="nx"&gt;total&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;current&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nx"&gt;total&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;current&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;addSubtract&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;x&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;nums&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="c1"&gt;// Recursive function that accumulates numbers for the operation.&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;f&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;y&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;nums&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;y&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;f&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="c1"&gt;// When the recursive function is type cast to a number,&lt;/span&gt;
  &lt;span class="c1"&gt;//   reduce the accumulated numbers.&lt;/span&gt;
  &lt;span class="nx"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;valueOf&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;nums&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;reduce&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;addSubtractReducer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="c1"&gt;// Return the recursive function, having added the first digit.&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;f&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;I defined the reducer function outside of the main function for readability. You may prefer including it in the function for better encapsulation.&lt;/p&gt;

&lt;p&gt;The reducer merely alternates addition and subtraction. Given a running total and a new number, if it’s an even index, add; if it’s an odd index, subtract.&lt;/p&gt;

&lt;p&gt;The recursive function &lt;code&gt;f&lt;/code&gt; is used to curry parameters. Every function call to &lt;code&gt;f&lt;/code&gt; just returns &lt;code&gt;f&lt;/code&gt;, allowing you to call it ad nauseum, each time adding the new parameter to the array of numbers that we will add/subtract.&lt;/p&gt;

&lt;p&gt;The function &lt;code&gt;f&lt;/code&gt; has a &lt;code&gt;valueOf&lt;/code&gt; property. When we type cast &lt;code&gt;f&lt;/code&gt; to a number, this property will get called. Starting with the first provided number (&lt;code&gt;x&lt;/code&gt;), this &lt;code&gt;valueOf&lt;/code&gt; property reducers the remaining numbers using the aforementioned alternating operations.&lt;/p&gt;

&lt;p&gt;The first call to &lt;code&gt;addSubtract&lt;/code&gt; then returns the recursive function &lt;code&gt;f&lt;/code&gt; after having created it.&lt;/p&gt;

&lt;h1&gt;
  
  
  Limitations 🙅
&lt;/h1&gt;

&lt;p&gt;In typical interview fashion, this solution is not perfect. If an interviewer were to grill you about limitations, this has weird behaviors when caching the return value of any of the function calls. Each function call beyond the first call to &lt;code&gt;addSubtract&lt;/code&gt; will be using the same array of &lt;code&gt;nums&lt;/code&gt;. This may cause unintended behavior.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;addTo1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;addSub&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// nums = [1]&lt;/span&gt;
&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="nx"&gt;addTo1&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 3             nums = [ 1, 2 ]&lt;/span&gt;
&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="nx"&gt;addTo1&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 1             nums = [ 1, 2, 2 ]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;nums&lt;/code&gt; array is stored inside &lt;code&gt;addTo1&lt;/code&gt;. The first call adds 2 to the value. The second call subtracts 2 from the value. This can be resolved by returning a new instance of an array for each function call. The original interview question did not stipulate this as a requirement, so I opted to provide the solution with less code complexity.&lt;/p&gt;

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

&lt;p&gt;I loved the obscurity of this problem, and users seemed to enjoy my solution. I decided I would share out of love for JavaScript language. If you are an interviewer, &lt;em&gt;do not&lt;/em&gt; ask this question during interviews. Make sure your curried examples have the same number of parameters or a terminating method. As a JavaScript expert, I do not believe this is a good interview question for JavaScript comprehension. This knowledge makes for a good puzzle, but not for a better developer. If you are an interviewee, do not expect this during an interview. Ask the interviewer for clarification on the different parameter lengths. It was probably a mistake on their part. (If it wasn’t, at least now you know how to solve it!)&lt;/p&gt;

&lt;p&gt;If you liked this article, feel free to give it a heart or a unicorn. It’s quick, it’s easy, and it’s free! If you have any questions or relevant insight, please leave a comment.&lt;/p&gt;

&lt;p&gt;To read more of my columns or contact me, you can find me on &lt;a href="https://www.linkedin.com/in/charles-stover"&gt;LinkedIn&lt;/a&gt;, &lt;a href="https://medium.com/@Charles_Stover"&gt;Medium&lt;/a&gt;, and &lt;a href="https://twitter.com/CharlesStover"&gt;Twitter&lt;/a&gt;, or &lt;a href="https://charlesstover.com/"&gt;check out my portfolio on CharlesStover.com&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>beginners</category>
      <category>webdev</category>
      <category>algorithms</category>
    </item>
    <item>
      <title>Manage global state with React hooks.</title>
      <dc:creator>Charles Stover</dc:creator>
      <pubDate>Wed, 05 Jun 2019 23:06:25 +0000</pubDate>
      <link>https://forem.com/charlesstover/manage-global-state-with-react-hooks-2692</link>
      <guid>https://forem.com/charlesstover/manage-global-state-with-react-hooks-2692</guid>
      <description>&lt;p&gt;Since the announcement of experimental Hooks in React 16.7, they have taken the React community by storm.&lt;/p&gt;

&lt;p&gt;Unfortunately, the same way class components only manage local state, the built-in &lt;code&gt;useState&lt;/code&gt; React hook only manages &lt;em&gt;local&lt;/em&gt; state in functional components. Global state management is still left to higher-order components and community-contributed endeavors.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://github.com/CharlesStover/reactn#readme"&gt;&lt;code&gt;reactn&lt;/code&gt; package&lt;/a&gt;, while also targeting class components, offers React hooks for accessing and managing global state in functional components. The ReactN package intends to integrate global state into React as if it were native functionality. In contrast to libraries like MobX and Redux, which are state-first solutions to state management, ReactN aims to be a React-first solution to global state management.&lt;/p&gt;

&lt;p&gt;To read more about or contribute to the ReactN project, &lt;a href="https://github.com/CharlesStover/reactn"&gt;the GitHub repository is welcoming to the community&lt;/a&gt;. To install ReactN, use &lt;code&gt;npm install reactn&lt;/code&gt; or &lt;code&gt;yarn add reactn&lt;/code&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  A useState Overview 🏁
&lt;/h1&gt;

&lt;p&gt;Analogous to the built-in React hook &lt;code&gt;useState&lt;/code&gt;, the &lt;code&gt;useGlobal&lt;/code&gt; hook of ReactN behaves as similar as possible, with a few key differences. To clearly identify these differences, I’ll first provide &lt;code&gt;useState&lt;/code&gt;’s behavior.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;useState&lt;/code&gt; function takes a default value and returns a 2-item array, where the first item is the state value and the second item is a function that updates that state value.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setValue&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;DEFAULT_VALUE&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;MyComponent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="nx"&gt;avatar&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setAvatar&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;anonymous.png&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;img&lt;/span&gt;
      &lt;span class="nx"&gt;alt&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Avatar&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
      &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{()&lt;/span&gt; &lt;span class="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;newAvatar&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Enter your avatar URL:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nx"&gt;setAvatar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;newAvatar&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;}}&lt;/span&gt;
      &lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;avatar&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="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 above example, &lt;code&gt;MyComponent&lt;/code&gt; renders an image &lt;code&gt;anonymous.png&lt;/code&gt; (because that is the default value of the state). When you click the image, you are prompted for a new avatar URL. The functional component’s state updates with this new URL, and it re-renders (due to state change), displaying the image you entered instead.&lt;/p&gt;

&lt;p&gt;This works great if you want to track the avatar &lt;em&gt;only in this component&lt;/em&gt;. But what if you have multiple components that display the user’s avatar? Or multiple instances of this same component? Each instance of &lt;code&gt;MyComponent&lt;/code&gt; will have its own instance of state, meaning each instance of &lt;code&gt;MyComponent&lt;/code&gt; can have a &lt;em&gt;different state&lt;/em&gt;. In many cases like these, developers opt for a &lt;em&gt;global state&lt;/em&gt; instead — insuring that all components are in sync with each other. If one component updates the user’s avatar, then all other components displaying the user’s avatar need to update too.&lt;/p&gt;

&lt;h1&gt;
  
  
  Global State Differences 🆚
&lt;/h1&gt;

&lt;p&gt;An important distinction when dealing with global state is how nonsensical it is to have a &lt;em&gt;default value&lt;/em&gt; when instantiating the state. If every component that relied on the user’s avatar had to have a default value, then the value isn’t really global: The components would not be in sync with each other, because each one would have its own, different value. You can give them each the same default value, but at that point you are not using &lt;a href="https://en.wikipedia.org/wiki/Don%27t_repeat_yourself"&gt;DRY code&lt;/a&gt;. Every time you want to change the default value, you have to go through the effort of changing it on &lt;em&gt;every component&lt;/em&gt;. Not only is that a huge annoyance, but it opens you up for error when one of the components coincidentally is forgotten about during the change.&lt;/p&gt;

&lt;p&gt;Because of this, global state is typically instantiated &lt;em&gt;outside&lt;/em&gt; of the components that use it. If the global state is given a value up front, then the components don’t need to provide a default value in case one does not already exist — it does already exist.&lt;/p&gt;

&lt;h1&gt;
  
  
  Instantiating the Global State 🌞
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://github.com/charlesStover/reactn#install"&gt;With ReactN, you can instantiate the global state&lt;/a&gt; with the &lt;code&gt;setGlobal&lt;/code&gt; helper function. Just provide the state object, and you’re done.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;setGlobal&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;reactn&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;setGlobal&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;avatar&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;anonymous.png&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It is recommended that this occur before &lt;code&gt;ReactDOM.render&lt;/code&gt;, because you typically want the state to exist before any components attempt to mount.&lt;/p&gt;

&lt;h1&gt;
  
  
  Using the Global State 🌎
&lt;/h1&gt;

&lt;p&gt;As mentioned, using the global state is meant to be as straightforward as using the local state. It is a React hook, prefixed with &lt;code&gt;use&lt;/code&gt;, placed at the top of your functional component, that returns a 2-item array where the first item is the state value and the second item is a function that updates the state value. Since the default value is instantiated elsewhere, you do not pass the default value as a parameter to the global state hook; instead, it receives the &lt;em&gt;property name&lt;/em&gt; of the global state that you want to access. The global state is an object of many different values that you may want to manage throughout your entire application, not a single value. In the instantiation example, we created an &lt;code&gt;avatar&lt;/code&gt; property, so we will access it here.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useGlobal&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;reactn&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;MyComponent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="nx"&gt;avatar&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setAvatar&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useGlobal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;avatar&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;img&lt;/span&gt;
      &lt;span class="nx"&gt;alt&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Avatar&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
      &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{()&lt;/span&gt; &lt;span class="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;newAvatar&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Enter your avatar URL:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nx"&gt;setAvatar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;newAvatar&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;}}&lt;/span&gt;
      &lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;avatar&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="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;That’s it. We changed &lt;code&gt;useState&lt;/code&gt; to &lt;code&gt;useGlobal&lt;/code&gt; and we replaced the default state value with the property we wanted to access. Whenever the global property avatar is updated by any component, all components using &lt;code&gt;useGlobal('avatar')&lt;/code&gt; will re-render with the new value.&lt;/p&gt;

&lt;h1&gt;
  
  
  Can I access the entire global state? 👪
&lt;/h1&gt;

&lt;p&gt;Yes! If you do not provide a property to &lt;code&gt;useGlobal&lt;/code&gt;, it will return &lt;em&gt;the entire global state&lt;/em&gt; for you to use as you please.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;MyComponent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="nb"&gt;global&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setGlobal&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useGlobal&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;img&lt;/span&gt;
      &lt;span class="nx"&gt;alt&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Avatar&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
      &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{()&lt;/span&gt; &lt;span class="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;newAvatar&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Enter your avatar URL:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nx"&gt;setGlobal&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
          &lt;span class="na"&gt;avatar&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;newAvatar&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;
      &lt;span class="p"&gt;}}&lt;/span&gt;
      &lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nb"&gt;global&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;avatar&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The same as when you provide a specific property, your component will only re-render if you access a property, not any time the global state is updated. This may be useful if you want to conditionally subscribe to certain properties. Your component will only re-render &lt;em&gt;if it accesses&lt;/em&gt; &lt;code&gt;global.property&lt;/code&gt; instead of every time &lt;code&gt;global.property&lt;/code&gt; updates.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;MyComponent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="nb"&gt;global&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setGlobal&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useGlobal&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="nb"&gt;global&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;global&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;global&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;y&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 above example, if &lt;code&gt;global.x&lt;/code&gt; is truthy, your component will only re-render when the &lt;code&gt;x&lt;/code&gt; property of the global state updates, not when the &lt;code&gt;y&lt;/code&gt; property of the global state updates. This is because the &lt;code&gt;y&lt;/code&gt; property of the global state does not impact the render of your component at all!&lt;/p&gt;

&lt;p&gt;If the &lt;code&gt;x&lt;/code&gt; property is falsey, your component will update whenever either &lt;code&gt;x&lt;/code&gt; or &lt;code&gt;y&lt;/code&gt; update. This is because both &lt;code&gt;x&lt;/code&gt; and &lt;code&gt;y&lt;/code&gt; changes will impact the render of your component.&lt;/p&gt;

&lt;p&gt;The “magic” here is simply that your component re-renders when there is a change in a global state property &lt;em&gt;that your component has accessed&lt;/em&gt;. Above, if &lt;code&gt;x&lt;/code&gt; is truthy, the &lt;code&gt;y&lt;/code&gt; property is &lt;em&gt;never accessed&lt;/em&gt;. The component returns before ever getting the chance. If &lt;code&gt;x&lt;/code&gt; is falsey, the &lt;code&gt;y&lt;/code&gt; property &lt;em&gt;is&lt;/em&gt; accessed.&lt;/p&gt;

&lt;p&gt;If you were to &lt;code&gt;useGlobal('x')&lt;/code&gt; and &lt;code&gt;useGlobal('y')&lt;/code&gt;, you would be accessing both the &lt;code&gt;x&lt;/code&gt; and &lt;code&gt;y&lt;/code&gt; properties — even if you were to ignore &lt;code&gt;y&lt;/code&gt;. As a result, your component would update when the unused &lt;code&gt;y&lt;/code&gt; property is changed.&lt;/p&gt;

&lt;h1&gt;
  
  
  What about Reducers? 🤔
&lt;/h1&gt;

&lt;p&gt;React 16.7 introduced a beautiful hook alongside &lt;code&gt;useState&lt;/code&gt; known as &lt;code&gt;useReducer&lt;/code&gt;. The &lt;code&gt;useReducer&lt;/code&gt; hook allows you to pass a reducer function and initial state. It returns the state and a dispatch function. Unlike &lt;code&gt;setState&lt;/code&gt; returned by &lt;code&gt;useState&lt;/code&gt;, the dispatch function passes your arguments along to the reducer function.&lt;/p&gt;

&lt;p&gt;Here is the reducer demonstrated by the React documentation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;initialState&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;count&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;reducer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;switch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;reset&lt;/span&gt;&lt;span class="dl"&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;initialState&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;increment&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;count&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;decrement&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;count&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;Counter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;dispatch&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useReducer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;reducer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;count&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;initialCount&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;reset&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;reset&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;increment&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;increment&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;decrement&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;decrement&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
      &lt;span class="nx"&gt;Count&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;reset&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Reset&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;increment&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;+&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;decrement&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;-&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the above example, &lt;code&gt;useReducer&lt;/code&gt; returns the state, which defaults to &lt;code&gt;{ count: 0 }&lt;/code&gt;, and a function that passes your parameters on to the reducer. The reducer takes the current state and your parameters to determine what the new state should be. Since actions such as &lt;code&gt;{ type: 'increment' }&lt;/code&gt; depend on the current state, the reducer returns the current state plus one.&lt;/p&gt;

&lt;p&gt;ReactN uses &lt;code&gt;useDispatch&lt;/code&gt; to handle reducers. The above example using global state would look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useDispatch&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;reactn&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;setGlobal&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;count&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;reducer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;switch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;reset&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;increment&lt;/span&gt;&lt;span class="dl"&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;count&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;decrement&lt;/span&gt;&lt;span class="dl"&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;count&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;Counter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="c1"&gt;// Subscribe to changes to count, because our view depends on it.&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useGlobal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;count&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// Dispatch changes to count using our reducer function.&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;dispatch&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useDispatch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;reducer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;count&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;reset&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;reset&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;increment&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;increment&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;decrement&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;decrement&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
      &lt;span class="nx"&gt;Count&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;reset&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Reset&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;increment&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;+&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;decrement&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;-&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Summary 📝
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Similarities:
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;useGlobal&lt;/code&gt; and &lt;code&gt;useDispatch&lt;/code&gt; are React hooks.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;useGlobal&lt;/code&gt; returns a value and a function for changing that value.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;useDispatch&lt;/code&gt; supports reducers.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;useDispatch&lt;/code&gt; returns a function for changing the current state.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Differences:
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;useGlobal&lt;/code&gt; takes an property name instead of an initial value.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;useGlobal&lt;/code&gt; can return the entire global state by not providing a parameter.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;useDispatch&lt;/code&gt; takes a property name in addition to a reducer.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;useDispatch&lt;/code&gt; does not (currently) return the value of the property, so as not to subscribe to it.

&lt;ul&gt;
&lt;li&gt;If your Component only updates the value, it does not need to re-render when that value changes. It may not display that value at all.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To install ReactN, use &lt;code&gt;npm install reactn&lt;/code&gt; or &lt;code&gt;yarn add reactn&lt;/code&gt;.&lt;/p&gt;

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

&lt;p&gt;Community feedback and pull requests for improving the &lt;code&gt;useGlobal&lt;/code&gt; and &lt;code&gt;useDispatch&lt;/code&gt; React hooks, as well as &lt;a href="https://github.com/charlesStover/reactn#readme"&gt;the plethora of other global state features of the ReactN package&lt;/a&gt;, are appreciated on &lt;a href="https://github.com/charlesStover/reactn"&gt;the GitHub repository&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you liked this article, feel free to give it a heart or unicorn. It’s quick, it’s easy, and it’s free! If you have any questions or relevant great advice, please leave them in the comments below.&lt;/p&gt;

&lt;p&gt;To read more of my columns, you may follow me on &lt;a href="https://www.linkedin.com/in/charles-stover"&gt;LinkedIn&lt;/a&gt;, &lt;a href="https://medium.com/@Charles_Stover"&gt;Medium&lt;/a&gt;, and &lt;a href="https://twitter.com/CharlesStover"&gt;Twitter&lt;/a&gt;, or &lt;a href="https://charlesstover.com/"&gt;check out my portfolio on CharlesStover.com&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>react</category>
      <category>reactnative</category>
      <category>javascript</category>
      <category>reactn</category>
    </item>
    <item>
      <title>React Suspense with the Fetch API</title>
      <dc:creator>Charles Stover</dc:creator>
      <pubDate>Wed, 05 Jun 2019 21:21:09 +0000</pubDate>
      <link>https://forem.com/charlesstover/react-suspense-with-the-fetch-api-374j</link>
      <guid>https://forem.com/charlesstover/react-suspense-with-the-fetch-api-374j</guid>
      <description>&lt;p&gt;&lt;em&gt;Dan Abramov, in response to a React developer asking why Suspense was not responding to the fetch API:&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsnxskrvsqywduo25f18x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsnxskrvsqywduo25f18x.png" width="565" height="148"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;From the legend Dan Abramov himself, we receive such gems as “There is [no data fetching solution compatible with React Suspense] that exists yet,” and “[React Cache] will be the first one,” and “Suspense is limited to code splitting.”&lt;/p&gt;

&lt;p&gt;If I have one thing to tell Daniel “Abra Cadabra” Abramov, besides how impressed I am with his work, it’s this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo0inbhxw7jsp9o9ofhwl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo0inbhxw7jsp9o9ofhwl.png" width="800" height="465"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let’s reveal the magic behind the curtain that is React Suspense. For educational purposes, I’ll cover how I created this package.&lt;/p&gt;

&lt;h1&gt;
  
  
  Shut Up and Give Me the Package! 💰
&lt;/h1&gt;

&lt;p&gt;If you’re just here for solutions, I don’t blame you. You can find &lt;a href="https://www.npmjs.com/package/fetch-suspense" rel="noopener noreferrer"&gt;&lt;code&gt;fetch-suspense&lt;/code&gt; on NPM&lt;/a&gt; and the most extensive documentation of your life on &lt;a href="https://github.com/CharlesStover/fetch-suspense" rel="noopener noreferrer"&gt;the GitHub repository&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;useFetch&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;fetch-suspense&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;MyComponent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="c1"&gt;// "Look! In the example! It's a fetch() request! It's a hook!"&lt;/span&gt;
  &lt;span class="c1"&gt;//   "No! It's kind of like both at the same time."&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;serverResponse&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useFetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/path/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="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="c1"&gt;// The return value is the body of the server's response.&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&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;serverResponse&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;;
&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  How Does Suspense Work? 🔮
&lt;/h1&gt;

&lt;p&gt;A lot of the new React features are built into the React library, as opposed to being external packages, due to the performance benefits of being tightly coupled to the engine that powers React, known as &lt;em&gt;React Fiber&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Due to React Fiber’s direct integration with features such as Suspense and hooks, you cannot create a verbatim copy of Suspense in React 16.5. However, you can probably make a less performant polyfill. I’ll use some polyfill examples so that you can conceptualize what is happening with Suspense.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Suspense&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Component&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;componentDidCatch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setState&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fallback&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="cm"&gt;/*
&amp;lt;Suspense fallback={&amp;lt;Loading /&amp;gt;}&amp;gt;
  &amp;lt;ErrorThrower /&amp;gt;
&amp;lt;/Suspense&amp;gt;
*/&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here is ye olde class component: a fossil remnant of yonder days of React development. The &lt;code&gt;componentDidCatch&lt;/code&gt; method is a method that fires whenever a child component throws an error. This allows you to replace uncaught JavaScript errors with a nice UI for your users or otherwise implement important logic during application errors.&lt;/p&gt;

&lt;p&gt;What the above does is mounts Suspense. Since there is no error in the local state, the children of Suspense are mounted too. In this case, the &lt;code&gt;&amp;lt;ErrorThrower /&amp;gt;&lt;/code&gt; component is mounted, and it throws an error.&lt;/p&gt;

&lt;p&gt;That error bubbles up to the Suspense instance, where the &lt;code&gt;componentDidCatch&lt;/code&gt; method receives it. It handles that error by saving it to its state, causing it to re-render.&lt;/p&gt;

&lt;p&gt;Now that it has rendered with an error in its local state, it no longer renders its children prop, nor the &lt;code&gt;&amp;lt;ErrorThrower /&amp;gt;&lt;/code&gt; devil-child as a result. Instead, it renders its &lt;code&gt;fallback&lt;/code&gt; prop, which we have set to a nice &lt;code&gt;&amp;lt;Loading /&amp;gt;&lt;/code&gt; modal.&lt;/p&gt;

&lt;p&gt;This is how Suspense works now, except instead of throwing errors, &lt;em&gt;JavaScript Promises&lt;/em&gt; are thrown. When Suspense catches a Promise, it &lt;em&gt;re-renders&lt;/em&gt;, displaying the fallback prop instead of the children that previous threw a Promise. When the Promise resolves, it &lt;em&gt;re-renders again&lt;/em&gt;; this time no longer displaying the &lt;code&gt;fallback&lt;/code&gt; prop, and instead attempting to re-render the original children, under the presumption that the children are now ready to be rendered without throwing Promises around like they’re meaningless.&lt;/p&gt;

&lt;p&gt;An implementation may look something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Suspense&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Component&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;promise&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;componentDidCatch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="c1"&gt;// Drake meme where he says no to errors here.&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;e&lt;/span&gt; &lt;span class="k"&gt;instanceof&lt;/span&gt; &lt;span class="nb"&gt;Error&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="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// Drake meme where he says yes to promises here.&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;e&lt;/span&gt; &lt;span class="k"&gt;instanceof&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setState&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="na"&gt;promise&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;e&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="c1"&gt;// When the promise finishes, go back to rendering the original children.&lt;/span&gt;
        &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setState&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;promise&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;
      &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// This line isn't compatible with the Drake meme format.&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;promise&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fallback&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="cm"&gt;/*
&amp;lt;Suspense fallback={&amp;lt;Loading /&amp;gt;}&amp;gt;
  &amp;lt;PromiseThrower /&amp;gt;
&amp;lt;/Suspense&amp;gt;
*/&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It’s important to note here that the original children &lt;em&gt;attempted to render&lt;/em&gt; before the fallback occurred. It never succeeded.&lt;/p&gt;

&lt;h1&gt;
  
  
  How Does This Apply to Fetch Hooks? 🎣
&lt;/h1&gt;

&lt;p&gt;What you should have gathered by now is that the fetch hook will need to &lt;em&gt;throw Promises&lt;/em&gt;. So it does. That promise is conveniently the fetch request. When Suspense receives that thrown fetch request, it falls back to rendering its &lt;code&gt;fallback&lt;/code&gt; prop. When that fetch request completes, it attempts to render the component again.&lt;/p&gt;

&lt;p&gt;There’s just one little tricky dicky problem with that — the component that threw the fetch request had only &lt;em&gt;attempted&lt;/em&gt; to render, but did not succeed. In fact, it is not a part of the &lt;code&gt;fallback&lt;/code&gt; at all! It has no instance. It never mounted. It has no state (not even a React hook state); it has no component lifecycle or effects. So when it &lt;em&gt;attempts&lt;/em&gt; to render again, how does it know the response of this fetch request? Suspense isn’t passing it, and it — not being instantiated — cannot have data attached to it.&lt;/p&gt;

&lt;h1&gt;
  
  
  Golly, How Do You Solve That Conundrum? 🤔
&lt;/h1&gt;

&lt;p&gt;We solve it with memoization!&lt;/p&gt;

&lt;p&gt;“Like that fancy new &lt;code&gt;React.memo&lt;/code&gt; feature?”&lt;/p&gt;

&lt;p&gt;“Yes!” (in concept)&lt;/p&gt;

&lt;p&gt;“No!” (more literally)&lt;/p&gt;

&lt;p&gt;It does not use &lt;code&gt;React.memo&lt;/code&gt;, which memoizes React components based on their props. Instead, I use an array of infinite depth to memoize the parameters passed to fetch.&lt;/p&gt;

&lt;p&gt;If a request comes in to fetch data that has been requested before (the second attempt to instantiate after the first attempt failed with a Promise), then it simply returns the data that eventually resolved from the first request’s Promise. If this is a fresh request, then we fetch it, cache it in the memoization array, and throw the fetch Promise. By comparing the current request to all entries in the memoization array, we know if we have dispatched this request before.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;deepEqual&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;deep-equal&lt;/span&gt;&lt;span class="dl"&gt;'&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;FetchCache&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;fetch&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="k"&gt;void&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;any&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;init&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;RequestInit&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;input&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;RequestInfo&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fetchCaches&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;FetchCache&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;useFetch&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;RequestInfo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;init&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;RequestInit&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;for &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;fetchCache&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;fetchCaches&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="c1"&gt;// The request hasn't changed since the last call.&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nf"&gt;deepEqual&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;fetchCache&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
      &lt;span class="nf"&gt;deepEqual&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;init&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;fetchCache&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;init&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="c1"&gt;// If we logged an error during this fetch request, THROW the error.&lt;/span&gt;
      &lt;span class="k"&gt;if &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;prototype&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;hasOwnProperty&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fetchCache&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;error&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="nx"&gt;fetchCache&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;

      &lt;span class="c1"&gt;// If we received a response to this fetch request, RETURN it.&lt;/span&gt;
      &lt;span class="k"&gt;if &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;prototype&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;hasOwnProperty&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fetchCache&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;response&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;fetchCache&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;

      &lt;span class="c1"&gt;// If we do not have a response or error, THROW the promise.&lt;/span&gt;
      &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="nx"&gt;fetchCache&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fetch&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="c1"&gt;// The request is new or has changed.&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="na"&gt;fetchCache&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;FetchCache&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;

      &lt;span class="c1"&gt;// Make the fetch request.&lt;/span&gt;
      &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;init&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="c1"&gt;// Parse the response.&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

          &lt;span class="c1"&gt;// Support JSON.&lt;/span&gt;
          &lt;span class="k"&gt;if &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;prototype&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;hasOwnProperty&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;headers&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="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
          &lt;span class="p"&gt;}&lt;/span&gt;

          &lt;span class="c1"&gt;// Not JSON.&lt;/span&gt;
          &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;text&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="p"&gt;})&lt;/span&gt;

        &lt;span class="c1"&gt;// Cache the response for when this component&lt;/span&gt;
        &lt;span class="c1"&gt;//   attempts to render again later.&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nx"&gt;fetchCache&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;})&lt;/span&gt;

        &lt;span class="c1"&gt;// Cache the error for when this component&lt;/span&gt;
        &lt;span class="c1"&gt;//   attempts to render again later.&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&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;fetchCache&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}),&lt;/span&gt;
    &lt;span class="nx"&gt;init&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;input&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="c1"&gt;// Add this metadata to the memoization array.&lt;/span&gt;
  &lt;span class="nx"&gt;fetchCaches&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fetchCache&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// Throw the Promise! Suspense to the rescue!&lt;/span&gt;
  &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="nx"&gt;fetchCache&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fetch&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;h1&gt;
  
  
  That Sounds Like a Memory Leak 💧
&lt;/h1&gt;

&lt;p&gt;It can be a feature &lt;em&gt;or&lt;/em&gt; a bug!&lt;/p&gt;

&lt;p&gt;But if you think it’s a bug in your project, you can invalidate the cache by providing a lifespan in milliseconds to the fetch request. Passing a third parameter (a number) to the &lt;code&gt;useFetch&lt;/code&gt; hook will tell it to remove the metadata from the memoization array after that many milliseconds. We implement it as easily as so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// NEW: lifespan parameter&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;useFetch&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;RequestInfo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;init&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;RequestInit&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;lifespan&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;number&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="c1"&gt;// ...&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="na"&gt;fetchCache&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;FetchCache&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;

      &lt;span class="c1"&gt;// Make the fetch request.&lt;/span&gt;
      &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;init&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="cm"&gt;/* ... */&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="cm"&gt;/* ... */&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="cm"&gt;/* ... */&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="c1"&gt;// Invalidate the cache.&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

          &lt;span class="c1"&gt;// If the user defined a lifespan,&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;lifespan&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

            &lt;span class="c1"&gt;// Wait for the duration of the lifespan,&lt;/span&gt;
            &lt;span class="nf"&gt;setTimeout&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="c1"&gt;// Find this fetch request and kill it&lt;/span&gt;
                &lt;span class="c1"&gt;//   from the memoization array.&lt;/span&gt;
                &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;fetchCaches&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;indexOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fetchCache&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;index&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                  &lt;span class="nx"&gt;fetchCaches&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;splice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;
              &lt;span class="p"&gt;},&lt;/span&gt;
              &lt;span class="nx"&gt;lifespan&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="c1"&gt;// ...&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When the fetch has completed, and we’ve updated the metadata, tick-tock. It’s important that the lifespan timer occurs after the &lt;code&gt;catch&lt;/code&gt; of the Promise, because we want it to set even if an error occurred.&lt;/p&gt;

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

&lt;p&gt;When Dan Abramov tells you that you can’t do something, &lt;em&gt;you do it&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;If you liked this article, feel free to give it a heart or a unicorn. It’s quick, it’s easy, and it’s free! If you have any questions or relevant great advice, please leave them in the comments below.&lt;/p&gt;

&lt;p&gt;To read more of my columns, you may follow me on &lt;a href="https://www.linkedin.com/in/charles-stover" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;, &lt;a href="https://medium.com/@Charles_Stover" rel="noopener noreferrer"&gt;Medium&lt;/a&gt;, and &lt;a href="https://twitter.com/CharlesStover" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt;, or &lt;a href="https://charlesstover.com/" rel="noopener noreferrer"&gt;check out my portfolio on CharlesStover.com&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>react</category>
      <category>reactnative</category>
      <category>javascript</category>
      <category>webdev</category>
    </item>
    <item>
      <title>How to convert withRouter to a React hook.</title>
      <dc:creator>Charles Stover</dc:creator>
      <pubDate>Wed, 05 Jun 2019 18:46:36 +0000</pubDate>
      <link>https://forem.com/charlesstover/how-to-convert-withrouter-to-a-react-hook-4ld9</link>
      <guid>https://forem.com/charlesstover/how-to-convert-withrouter-to-a-react-hook-4ld9</guid>
      <description>&lt;p&gt;One of the greatest benefits of React Hooks in the new v16.7 is the removal of the reliance on higher-order components. While in the process of migrating my class states to functional hooks, I was giddy at the opportunity to port my &lt;a href="https://github.com/CharlesStover/with-router/blob/master/README.md"&gt;with-router&lt;/a&gt; higher-order component to a hook as well. I have been using this custom implementation to re-render my components on route change. &lt;code&gt;react-router&lt;/code&gt;'s built-in &lt;code&gt;withRouter&lt;/code&gt; HOC does not re-render components on route change, and it is a &lt;a href="https://github.com/ReactTraining/react-router/blob/master/packages/react-router/docs/guides/blocked-updates.md"&gt;difficult issue&lt;/a&gt; to work around.&lt;/p&gt;

&lt;p&gt;This article should serve as a tutorial for implementing a React hook with pub-sub functionality. Pub-sub, short for “publish-subscribe,” is a programming methodology wherein a set of subscription processes become notified when an update is published. In short, when the location changes (the published event), I want to re-render my component (the listener subscription).&lt;/p&gt;

&lt;p&gt;The final product requires React Router v4.4 or greater, as previous versions of React Router did not expose the Router Context, which we are using to listen to location changes. If the latest version of React Router is not accessible to you, you can listen to the window history state as an alternative. I opted to use the same “single source of truth” that &lt;code&gt;react-router&lt;/code&gt; uses, insuring that my states are always in sync.&lt;/p&gt;

&lt;p&gt;You may use this package yourself via &lt;a href="https://www.npmjs.com/package/use-react-router"&gt;use-react-router on NPM&lt;/a&gt; or contribute to, fork, or otherwise spy on the &lt;a href="https://github.com/CharlesStover/use-react-router"&gt;open-source GitHub repository&lt;/a&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  The User Experience 🙃
&lt;/h1&gt;

&lt;p&gt;I start every project by asking the question, “What do I want to do?” This does not mean, “How do I want to implement this feature?” It means, as a developer, how do I wish this feature was already implemented. What do I want to &lt;em&gt;have&lt;/em&gt; to do to use this feature in the future? How do I make it &lt;em&gt;intuitive&lt;/em&gt; and &lt;em&gt;easy to use&lt;/em&gt;?&lt;/p&gt;

&lt;p&gt;Luckily, &lt;code&gt;withRouter&lt;/code&gt; is not a difficult implementation, so neither is its hook.&lt;/p&gt;

&lt;p&gt;I will want to import a hook from a default package export.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;useReactRouter&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;use-react-router&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I want to call that hook and &lt;em&gt;be done with it&lt;/em&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;history&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;location&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;match&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useReactRouter&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This declutters the history, location, and match props from my component and allows me to pick and choose which I want to have exist.&lt;/p&gt;

&lt;p&gt;I do not want to have to implement further logic to re-render on location change. I want that functionality to be already implemented, in stark contrast to &lt;code&gt;react-router&lt;/code&gt;'s implementation of the HOC. That’s just personal preference, and you may agree with their implementation instead. This tutorial will discuss how to implement either, as it is a common feature request, and it was highly relevant to my personal use case.&lt;/p&gt;

&lt;h1&gt;
  
  
  The Implementation
&lt;/h1&gt;

&lt;h2&gt;
  
  
  The Dependencies 👶
&lt;/h2&gt;

&lt;p&gt;First, our dependencies.&lt;/p&gt;

&lt;p&gt;We will need the router context from the &lt;code&gt;react-router&lt;/code&gt; package, as it contains the data we are wanting to access in our component, and we will need the &lt;code&gt;useContext&lt;/code&gt; hook from the react package to “hook” to the Router Context. Since we are implementing pub-sub functionality, we also need the &lt;code&gt;useEffect&lt;/code&gt; hook built into React. This will allow us to subscribe and unsubscribe from the location changes.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useContext&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useEffect&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;__RouterContext&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react-router&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Lastly, I am going to import &lt;code&gt;useForceUpdate&lt;/code&gt; from the &lt;a href="https://www.npmjs.com/package/use-force-update"&gt;&lt;code&gt;use-force-update&lt;/code&gt; NPM package&lt;/a&gt;. It is merely a shorthand for calling the &lt;code&gt;useState&lt;/code&gt; hook to force a re-render, which is what we’ll be doing when the location changes.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;useForceUpdate&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;use-force-update&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The Hook 🎣
&lt;/h2&gt;

&lt;p&gt;With our dependencies imported, we can begin writing the hook&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;useReactRouter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;forceUpdate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useForceUpdate&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;routerContext&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useContext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;__RouterContext&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="cm"&gt;/* TODO */&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;routerContext&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 begin by instantiating all other hooks that we’ll be needing. &lt;code&gt;forceUpdate&lt;/code&gt; is a now a function that, when called, re-renders the component. &lt;code&gt;routerContext&lt;/code&gt; is now the contents of the &lt;code&gt;react-router&lt;/code&gt; context: an object with &lt;code&gt;history&lt;/code&gt;, &lt;code&gt;location&lt;/code&gt;, and &lt;code&gt;match&lt;/code&gt; properties — the very same that you would expect to receive as props from &lt;code&gt;withRouter&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;If you do not want the re-rendering functionality,&lt;/strong&gt; you can stop here. You can remove the &lt;code&gt;forceUpdate&lt;/code&gt; variable, the &lt;code&gt;useEffect&lt;/code&gt; import, and &lt;a href="https://www.npmjs.com/package/use-force-update"&gt;&lt;code&gt;use-force-update&lt;/code&gt; dependency&lt;/a&gt;. I would advise using an external &lt;code&gt;useReactRouter&lt;/code&gt; hook over calling &lt;code&gt;useContext&lt;/code&gt; within your component solely because of the &lt;code&gt;__RouterContext&lt;/code&gt; name and &lt;code&gt;@next&lt;/code&gt; semvar currently needed to access React Router v4.4. Accessing this context may be subject to change, and making that adjustment in the single package is significantly less work than making that adjustment in every router-dependent component you use in your project. It is also ever-so-slightly more intuitive for developers to &lt;code&gt;useReactRouter&lt;/code&gt; than &lt;code&gt;useContext(__RouterContext)&lt;/code&gt; — the additional context import is redundant and unchanging.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Pub-Sub 📰
&lt;/h2&gt;

&lt;p&gt;To implement pub-sub behavior, we will want to &lt;code&gt;useEffect&lt;/code&gt;. This will allow us to subscribe on component mount and unsubscribe on component unmount. Theoretically, it will unsubscribe from an old context and re-subscribe to a new one if the router context were to change (a desirable behavior if that were to happen), but there’s no reason to assume that will ever happen.&lt;/p&gt;

&lt;p&gt;Replace our &lt;code&gt;/* TODO */&lt;/code&gt; with the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;useEffect&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="c1"&gt;// TODO: subscribe&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// TODO: unsubscribe&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="cm"&gt;/* TODO: memoization parameters here */&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;useEffect&lt;/code&gt; takes a function that will execute every mount and update. If that function returns a function, that second function will execute every unmount and pre-update.&lt;/p&gt;

&lt;p&gt;Where &lt;code&gt;effect1&lt;/code&gt; is the outer function and &lt;code&gt;effect2&lt;/code&gt; is the inner function, the component lifecycle executes like so:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mount &amp;gt; effect1 ... effect2 &amp;gt; update &amp;gt; effect1 ... effect2 &amp;gt; unmount
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The outer function executes immediately after a mount or update. The inner function &lt;em&gt;waits&lt;/em&gt; until the component is about to update or unmount before executing.&lt;/p&gt;

&lt;p&gt;Our goal is to subscribe to location changes once our component has mounted and unsubscribe to location changes just before our component unmounts.&lt;/p&gt;

&lt;p&gt;The memoization array of &lt;code&gt;useEffect&lt;/code&gt; says “do not execute these effect functions on update unless this array of parameters has changed.” We can use this to not continuously subscribe and unsubscribe to location changes just because the component re-rendered. As long as the router context is the same, we do not need to alter our subscription. Therefore, our memoization array can contain a single item: &lt;code&gt;[ routerContext ]&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;subscribe&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// TODO&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;unsubscribe&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// TODO&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="nx"&gt;routerContext&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;How do you subscribe to location changes? By passing a function to &lt;code&gt;routerContext.history.listen&lt;/code&gt;, that function will execute every time the router history changes. In this case, the function we want to execute is simply &lt;code&gt;forceUpdate&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;subscribe&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;routerContext&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;history&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;forceUpdate&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;unsubscribe&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// TODO&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="nx"&gt;routerContext&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And how do you unsubscribe from location changes? We can’t just let this subscription exist after the component unmounts — &lt;code&gt;forceUpdate&lt;/code&gt; will be called, but there won’t be a component to update!&lt;/p&gt;

&lt;p&gt;&lt;code&gt;routerContext.history.listen&lt;/code&gt; returns an unsubscribe function that, when called, removes the subscription listener (&lt;code&gt;forceUpdate&lt;/code&gt;) from the event.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;useEffect&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;unsubscribe&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;routerContext&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;history&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;forceUpdate&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;unsubscribe&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="nx"&gt;routerContext&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;Not that there is any benefit to this, but if you want to make this code a little shorter, you can:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;useEffect&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;unsubscribe&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;routerContext&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;history&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;forceUpdate&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;unsubscribe&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="nx"&gt;routerContext&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And even shorter:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;useEffect&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="nx"&gt;routerContext&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;history&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;forceUpdate&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="nx"&gt;routerContext&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;h1&gt;
  
  
  Where to Go From Here? 🔮
&lt;/h1&gt;

&lt;p&gt;The HOC implementation of &lt;code&gt;withRouter&lt;/code&gt; provided by the &lt;code&gt;react-router&lt;/code&gt; package pulls &lt;code&gt;history&lt;/code&gt;, &lt;code&gt;location&lt;/code&gt;, and &lt;code&gt;match&lt;/code&gt; from component props and gives them higher priority than the context API’s values. This is likely due to the &lt;code&gt;&amp;lt;Route&amp;gt;&lt;/code&gt; component providing these as props, and &lt;code&gt;match&lt;/code&gt;’s value needing to come from &lt;code&gt;Route&lt;/code&gt;'s path interpretation.&lt;/p&gt;

&lt;p&gt;While I have not harnessed this in my package yet, I think a solid next step would be to use the hooked component’s props as a parameter to &lt;code&gt;useReactRouter&lt;/code&gt;, allowing it to use the same prop prioritization.&lt;/p&gt;

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

&lt;p&gt;If you want to contribute to this open-source package or see it in &lt;em&gt;TypeScript&lt;/em&gt;, you can star it, fork it, open issues, or otherwise &lt;a href="https://github.com/CharlesStover/use-react-router/blob/master/src/use-react-router.ts"&gt;check it out on GitHub&lt;/a&gt;. You may use this package yourself via &lt;a href="https://www.npmjs.com/package/use-react-router"&gt;&lt;code&gt;use-react-router&lt;/code&gt; on NPM&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you liked this article, feel free to give it a heart or unicorn. It’s quick, it’s easy, and it’s free! If you have any questions or relevant great advice, please leave them in the comments below.&lt;/p&gt;

&lt;p&gt;To read more of my columns, you may follow me on &lt;a href="https://www.linkedin.com/in/charles-stover"&gt;LinkedIn&lt;/a&gt;, &lt;a href="https://medium.com/@Charles_Stover"&gt;Medium&lt;/a&gt;, and &lt;a href="https://twitter.com/CharlesStover"&gt;Twitter&lt;/a&gt;, or &lt;a href="https://charlesstover.com/"&gt;check out my portfolio on CharlesStover.com&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>react</category>
      <category>reactnative</category>
      <category>javascript</category>
      <category>typescript</category>
    </item>
    <item>
      <title>No-boilerplate global state management in React</title>
      <dc:creator>Charles Stover</dc:creator>
      <pubDate>Wed, 05 Jun 2019 17:20:22 +0000</pubDate>
      <link>https://forem.com/charlesstover/no-boilerplate-global-state-management-in-react-1o47</link>
      <guid>https://forem.com/charlesstover/no-boilerplate-global-state-management-in-react-1o47</guid>
      <description>&lt;p&gt;When your React application reaches a certain size and scope, attempting to manage state within component instances adds too much complexity, prop drilling, and code smell. Developers inevitably turn to &lt;em&gt;global&lt;/em&gt; state management tools, such as MobX or Redux, to solve these problems and make their lives simpler. I strongly endorse Redux and use it in my personal projects, but not all developers share my sentiment.&lt;/p&gt;

&lt;p&gt;I have worked on quite a few large projects that have demanded a global state powerhouse behind the React UI. No matter application size, team size, or member seniority, the almost universal opinion of these global state management packages has been overwhelmingly &lt;em&gt;negative&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;The top two complaints? &lt;em&gt;Boilerplate&lt;/em&gt; and &lt;em&gt;learning curve&lt;/em&gt;. While these packages solve a lot of problems and solve them well, it is not without cost. Developers are not happy with how many files, code blocks, and copy-pasting is required to set up or modify their global states. More importantly, junior developers have a hard time overcoming the learning curve required of them. Creating a global store is a nightmare for some, and extending it with functionality, such as developer tooling and asynchronous features, was a task that took too much company time and caused too many employee headaches.&lt;/p&gt;

&lt;p&gt;I polled many developers to gauge their top complaints when integrating global state management into their React applications. You can skip to the end of the list if you don’t want to read them all. These excerpts are merely outline common difficulties when integrating global state into React applications and barriers faced by real React developers.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;“Newer developers may require a longer ramp-up time along with proper training.”&lt;/li&gt;
&lt;li&gt;“New developers have a problem with flux architecture and functional concepts… They should essentially be producing events that describe how the application changes instead of imperatively doing it themselves. This is vastly different than the more familiar MVC-esque patterns.”&lt;/li&gt;
&lt;li&gt;“I found trying to manage a complex state tree in Redux very challenging and abandoned it early on for my app. I really struggled to understand what best practices are outside of simple to-do app examples. I just never really understood how to use Redux in a real-world app with a complex state.”&lt;/li&gt;
&lt;li&gt;“It often feels tedious to do trivial state changes.”&lt;/li&gt;
&lt;li&gt;“It takes junior developers some time to get their head around the magic of autoruns, reactions, etc. Debugging becomes harder when you have to step through MobX code in order get to your own.”&lt;/li&gt;
&lt;li&gt;“It’s annoying that Redux does not handle asynchronous actions out of the box. You have to spend a day figuring out this basic and essential use case. You have to research thunks and sagas. Then, you still have to figure out how to tie them in with actions. It’s a lot to deal with and makes you wish for good old Promises.”&lt;/li&gt;
&lt;li&gt;“For Redux, I dislike that it creates a side-effects vacuum, which has to be filled by a bunch of middlewares. There is a problem in that none of the middlewares out there are perfect.”&lt;/li&gt;
&lt;li&gt;“Whenever I use Redux, I ask myself, ‘What on earth was I thinking?’ It overcomplicates everything. Some would argue that the benefit of Redux is that you can choose the features you need (immutable, reselect, sagas, etc.); but in the end, you’ll be adding all of these to every project anyway.”&lt;/li&gt;
&lt;li&gt;“Redux requires a ton of files to establish a new reducer. A lot of the advantages in practice do not tend to be worth the disadvantages.”&lt;/li&gt;
&lt;li&gt;“Redux has too much boilerplate, and I have to maintain all of it.”&lt;/li&gt;
&lt;li&gt;“You really need to use decorators for MobX. The non-decorator syntax is not nice, and it’s a big dependency.” MobX currently weighs in at &lt;a href="https://bundlephobia.com/result?p=mobx@5.5.2"&gt;47kB&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;“Redux requires a ton of tedious code to do the most basic things: declare your action name in your action file, create a saga file, add it to your root sagas, create your action generator to call the saga, connect your component to Redux so it can access the store, write mapStateToProps which calls a selector, write your selector to get your user info out of the store, write a mapDispatchToProps so you can dispatch an action in your component, dispatch an action in your component’s componentDIdMount, add an action to handle the result of your network request, write a reducer that saves the user info to the store, add another action to handle an error, add another action to handle loading state, write selectors and reducers for the error and loading actions, call your selector in the render function of your component to get and display the data. Does that seem reasonable for a simple network request? Seems like a pile of hot garbage to me.” While I’m not as experienced with sagas, I will &lt;a href="https://dev.to/charlesstover/the-fetch-api-and-asynchronous-redux-state-1fgk"&gt;plug my methodology for handling API requests with redux thunk&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;“Global state packages are very cumbersome and complex to set up. They violate the KISS principle — Keep It Simple, Stupid.”&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;After this list, I feel the need to reiterate: I am a fan of Redux, and I use it on my personal projects. The purpose of this article is not to trash Redux or MobX, or to propose that they are flawed systems. It is to highlight a real issue: There is difficulty integrating these packages into real applications, and most of this difficulty seems to stem from the learning curve. These packages are “too clever” and are not as accessible to junior developers, who tend to make up the majority of contributors to projects.&lt;/p&gt;

&lt;p&gt;One piece of feedback I received explicitly blamed the users of the packages: “Users don’t put enough effort into evaluating their needs; don’t use [the packages] judiciously or as advised; don’t give a second thought to any dependencies they add; and never revisit their design decision, then complain about them.” I think they were onto something. I don’t think Redux or MobX are innately flawed, but I think there is a real difficulty in integrating them into enterprise projects. They may not be the best solution, not out of function, but out of complexity.&lt;/p&gt;

&lt;p&gt;I am hoping with the release of React 16.7 &lt;a href="https://reactjs.org/docs/hooks-intro.html"&gt;Hooks&lt;/a&gt; and its re-conceptualization of how a readable React application looks, we will see global state solutions that harness creative new methods that appeal to wider audiences. With the ultimate goal of no boilerplate and intuitive syntax, this article will offer my opinion on how a global state management system for React can be structured and finally my open-source attempt of that implementation.&lt;/p&gt;

&lt;p&gt;You may use this implementation yourself via &lt;a href="https://www.npmjs.com/package/reactn"&gt;&lt;code&gt;reactn&lt;/code&gt; on NPM&lt;/a&gt; or contribute to, fork, or otherwise spy on the &lt;a href="https://github.com/CharlesStover/reactn"&gt;open-source GitHub repository&lt;/a&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  Keep It Simple, Stupid 💋
&lt;/h1&gt;

&lt;h2&gt;
  
  
  An Intuitive Approach
&lt;/h2&gt;

&lt;p&gt;My personal take on the matter is that global state management systems appear to be designed with &lt;em&gt;global state management&lt;/em&gt; in mind, not &lt;em&gt;React&lt;/em&gt;. They are designed so broadly that the intention is to be usable even outside of React projects. That’s not a bad thing, but it is unintuitive for junior developers who may already be overwhelmed by learning React.&lt;/p&gt;

&lt;p&gt;React has state management built-in — &lt;code&gt;this.state&lt;/code&gt;, &lt;code&gt;this.setState&lt;/code&gt;, and the new &lt;code&gt;useState&lt;/code&gt; and &lt;code&gt;useReducer&lt;/code&gt; hooks. I posit that global state management should be as simple as local state management. The migration to or from global state should not require an entirely new skill set.&lt;/p&gt;

&lt;p&gt;We read from and write to a local component state using the following syntax:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Class Component&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;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setState&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Charles&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="c1"&gt;// Functional Component&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setName&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Default Name&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We should be able to harness the power of global state similarly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Class Component&lt;/span&gt;
&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;global&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setGlobal&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Charles&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="c1"&gt;// Functional Component&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setName&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useGlobal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;name&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each property on the global member variable &lt;code&gt;this.global&lt;/code&gt; can harness a &lt;a href="https://github.com/CharlesStover/reactn/blob/e56b63d99be8997f959c52b9c0baff872e05ebfb/src/object-get-listener.js"&gt;getter&lt;/a&gt; that subscribes that component instance to property changes in the global store. Whenever that property changes, any instance the accessed it re-renders. That way, updating property &lt;code&gt;name&lt;/code&gt; in the global store does not re-render a component that only accesses property &lt;code&gt;this.global.age&lt;/code&gt;, but it does re-render components that access &lt;code&gt;this.global.name&lt;/code&gt;, as would be intuitive behavior of a state change.&lt;/p&gt;

&lt;p&gt;As a technical necessity, a global &lt;em&gt;hook&lt;/em&gt; would need the property name (instead of a default value) in order to access that specific property. I would opt away from a default value on a global hook. Almost by definition, a global state property is to be accessed by multiple components. Having to put a default on each component, which should theoretically be the same default value for all instances of that property, is not &lt;a href="https://en.wikipedia.org/wiki/Don%27t_repeat_yourself"&gt;DRY code&lt;/a&gt;. Global defaults should be managed externally, such as an initializer.&lt;/p&gt;

&lt;p&gt;And if you want the entire global state object in a hook:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="nb"&gt;global&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setGlobal&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useGlobal&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Though a functional component, &lt;code&gt;global&lt;/code&gt; would be analogous to &lt;code&gt;this.global&lt;/code&gt; and &lt;code&gt;setGlobal&lt;/code&gt; would be analogous to &lt;code&gt;this.setGlobal&lt;/code&gt; in a class component.&lt;/p&gt;

&lt;h1&gt;
  
  
  No Boilerplate 🔩
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Minimal Setup or Modification
&lt;/h2&gt;

&lt;p&gt;When we strip a lot of the features of Redux or MobX that developers find unnecessary, tedious, or otherwise superfluous, there isn’t much boilerplate needed. Especially when we gear our package towards &lt;em&gt;React itself&lt;/em&gt; and not on being a global state solution for the Internet as a whole.&lt;/p&gt;

&lt;p&gt;If we want &lt;code&gt;this.global&lt;/code&gt; and &lt;code&gt;this.setGlobal&lt;/code&gt; in class components, then it needs to be on the class each component extends — &lt;code&gt;React.Component&lt;/code&gt; and &lt;code&gt;React.PureComponent&lt;/code&gt;. That new class, with global state functionality, would extend the original &lt;code&gt;React.Component&lt;/code&gt; or &lt;code&gt;React.PureComponent&lt;/code&gt;. There are a few different ways to go about this. I opted for what I would consider to be the easiest for any developer: a single byte change.&lt;/p&gt;

&lt;p&gt;The package, named &lt;a href="https://www.npmjs.com/package/reactn"&gt;ReactN&lt;/a&gt;, exports an exact copy of React, except the &lt;code&gt;Component&lt;/code&gt; and &lt;code&gt;PureComponent&lt;/code&gt; properties extend the originals by adding the &lt;code&gt;global&lt;/code&gt; member variable and &lt;code&gt;setGlobal&lt;/code&gt; method.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// before&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;reactn&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// after&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Whenever you add this single byte to a file, all references to &lt;code&gt;React.Component&lt;/code&gt; and &lt;code&gt;React.PureComponent&lt;/code&gt; now have global functionality built in, while all references to other React functionality, such as &lt;code&gt;React.createElement&lt;/code&gt; are completely unaltered. This is accomplished by copying the references to the same React package you are already using to a new object. &lt;a href="https://www.npmjs.com/package/reactn"&gt;ReactN&lt;/a&gt; is lightweight as a result, as opposed to a copy-paste clone of the React package, and it doesn’t modify the original React object at all.&lt;/p&gt;

&lt;p&gt;But what if you don’t want the React object that you import to have these new properties? I completely understand. The default import of &lt;a href="https://www.npmjs.com/package/reactn"&gt;ReactN&lt;/a&gt; also acts as a decorator.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;reactn&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;reactn&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="nd"&gt;reactn&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;MyComponent&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Component&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;render&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;global&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&amp;gt;&lt;/span&gt;&lt;span class="err"&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;No decorator support in your &lt;code&gt;create-react-app&lt;/code&gt;? Class decorators are easy to implement in vanilla ES6.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;reactn&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;reactn&lt;/span&gt;&lt;span class="dl"&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;MyComponent&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Component&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;render&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;global&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;;
&lt;/span&gt;  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;reactn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;MyComponent&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One of these three solutions should meet the style guidelines of your team, and any of the three options have no more than one line of “boilerplate” to implement.&lt;/p&gt;

&lt;p&gt;But what about setting up the store? The aforementioned initializer? The aforementioned Redux nightmare? My best solution thus far is to simply pass a state object synchronously, but I feel it’s an area that could use some improvement from community feedback.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;setGlobal&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;reactn&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;setGlobal&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;a&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;b&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Charles&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Forever 21&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  React Hooks 🎣
&lt;/h1&gt;

&lt;p&gt;“I’m sorry, is this 24 Oct. 2018? React &lt;em&gt;Hooks&lt;/em&gt; are here now, and I never have to use a class component again!”&lt;/p&gt;

&lt;p&gt;You’re right. React global state management solutions should harness the power of React Hooks — after all, functional components use &lt;code&gt;useState&lt;/code&gt;, so in order to be intuitive to what React developers already know and use, there should be an analogous global state hook.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useGlobal&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;reactn&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;MyComponent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="nx"&gt;localText&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setLocalText&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Hello world!&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="nx"&gt;globalText&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setGlobalText&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useGlobal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&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;localText&lt;/span&gt;&lt;span class="p"&gt;}...&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;globalText&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;;
&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can offer a completely analogous solution; and, as it should, it shares global state with the global &lt;code&gt;text&lt;/code&gt; property used in the class component demo. There’s no reason why functional and class components can’t share their global states. Using hooks-within-hooks, we can force a component to re-render when a global state property to which it is “hooked” changes — just as you would expect with local state.&lt;/p&gt;

&lt;p&gt;A little more versatile, we can use &lt;code&gt;useGlobal&lt;/code&gt; the same way class components use it. This may be more accessible to the user migrating from classes.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useGlobal&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;reactn&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;MyComponent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="nb"&gt;global&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setGlobal&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useGlobal&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt;
      &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;setGlobal&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
          &lt;span class="na"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;global&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;
      &lt;span class="p"&gt;}}&lt;/span&gt;
    &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nx"&gt;Click&lt;/span&gt; &lt;span class="nx"&gt;Me&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nb"&gt;global&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;setGlobal&lt;/code&gt; also accepts a function parameter, the same way &lt;code&gt;this.setState&lt;/code&gt; does.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;setGlobal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;oldGlobal&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;oldGlobal&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="p"&gt;}));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Reducers: Modern Staples of State Management 🔉
&lt;/h1&gt;

&lt;p&gt;With Redux’s dependency on reducers and React 16.7’s introduction of &lt;code&gt;useReducer&lt;/code&gt;, I simply couldn’t pretend that reducers aren’t a modern day implementation of state management. How do you manage a third party global state without the boilerplate of reducers?&lt;/p&gt;

&lt;p&gt;I’ve implemented two solutions. One, for class syntax:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;addReducer&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;reactn&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// this.dispatch.addCard('Ace of Spades')&lt;/span&gt;
&lt;span class="nx"&gt;addReducer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;addCard&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;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;card&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;cards&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cards&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;concat&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt; &lt;span class="nx"&gt;card&lt;/span&gt; &lt;span class="p"&gt;]),&lt;/span&gt;
&lt;span class="p"&gt;}));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This introduces the familiarity of Redux reducers with less boilerplate: the functions are smaller and easier to code split, and there are no higher-order components to cloud the React component tree. Altogether this, to me, feels more maintainable.&lt;/p&gt;

&lt;p&gt;The second solution is inspired by the functional &lt;code&gt;useReducer&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useDispatch&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;reactn&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;addCardReducer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cards&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;card&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
  &lt;span class="nx"&gt;cards&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;concat&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt; &lt;span class="nx"&gt;card&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;MyComponent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="c1"&gt;// addCard takes a card and concats it&lt;/span&gt;
  &lt;span class="c1"&gt;//   to the global state cards property.&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;addCard&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useDispatch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;addCardReducer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// &amp;lt;-- reducer function&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;cards&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// &amp;lt;-- the property being reduced&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// Display a button.&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt;
      &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

        &lt;span class="c1"&gt;// Add "Ace of Spades" to the global state.&lt;/span&gt;
        &lt;span class="nx"&gt;addCard&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Ace of Spades&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="nx"&gt;Click&lt;/span&gt; &lt;span class="nx"&gt;me&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Like &lt;code&gt;useReducer&lt;/code&gt;, you can use this returned dispatch function to modify the global state. Your reducers can thus be code split or even imported if that is preferred to the aforementioned &lt;code&gt;addReducer&lt;/code&gt;. If &lt;code&gt;addReducer&lt;/code&gt; is preferred, you can still access your added reducers in functional components via &lt;code&gt;const addCard = useDispatch('addCard');&lt;/code&gt;.&lt;/p&gt;

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

&lt;p&gt;This isn’t the documentation for &lt;a href="https://www.npmjs.com/package/reactn"&gt;ReactN&lt;/a&gt;, so I won’t detail the bells and whistles. I do want to outline a system that I believe is significantly more &lt;em&gt;intuitive&lt;/em&gt; to React developers, in hopes that it may inspire creativity that is targeted to React solutions. There is absolutely no reason a global state package should require so much boilerplate or add so much complexity to a project. All of the above takes up a whopping 4.3kB, and supports asynchronous state change out of the box (with no need for middleware).&lt;/p&gt;

&lt;p&gt;If you want to contribute to this project, it is &lt;a href="https://github.com/CharlesStover/reactn"&gt;open-source on GitHub&lt;/a&gt;, and I would be absolutely ecstatic for more community feedback. If you want to play around with this project, simply &lt;code&gt;npm install reactn&lt;/code&gt; or &lt;code&gt;yarn add reactn&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If you liked this article, feel free to give it a heart or unicorn. It’s quick, it’s easy, and it’s free! If you have any questions or relevant great advice, please leave them in the comments below.&lt;/p&gt;

&lt;p&gt;To read more of my columns, you may follow me on &lt;a href="https://www.linkedin.com/in/charles-stover"&gt;LinkedIn&lt;/a&gt;, &lt;a href="https://medium.com/@Charles_Stover"&gt;Medium&lt;/a&gt;, and &lt;a href="https://twitter.com/CharlesStover"&gt;Twitter&lt;/a&gt;, or &lt;a href="https://charlesstover.com/"&gt;check out my portfolio on CharlesStover.com&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>react</category>
      <category>reactnative</category>
      <category>javascript</category>
      <category>reactn</category>
    </item>
    <item>
      <title>The Fetch API and asynchronous Redux state</title>
      <dc:creator>Charles Stover</dc:creator>
      <pubDate>Wed, 05 Jun 2019 15:33:09 +0000</pubDate>
      <link>https://forem.com/charlesstover/the-fetch-api-and-asynchronous-redux-state-1fgk</link>
      <guid>https://forem.com/charlesstover/the-fetch-api-and-asynchronous-redux-state-1fgk</guid>
      <description>&lt;p&gt;If you are building a complex React application, you are likely using a back end service and an API. If you are managing state in React, you likely are using redux. Both are great choices that I would highly recommend for your React application's architecture. However, redux's out-of-the-box synchronous state manipulation is not particularly compatible with &lt;em&gt;asynchronous&lt;/em&gt; server responses, leaving many developers scratching their heads. There are &lt;a href="https://medium.com/r/?url=https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/readyState"&gt;&lt;em&gt;a lot&lt;/em&gt; of states&lt;/a&gt; involved in an asynchronous call, but isn't an API call just a single action?&lt;/p&gt;

&lt;p&gt;I would like to walk you through the standardized states involved in an asynchronous API call and their relationship to the redux store.&lt;/p&gt;

&lt;p&gt;By the end of this article, you should understand how to write an asynchronous redux action that handles each state of an API call. Each API call has the same states and logic behind when those states are triggered, so in order to prevent copy-pasting the same boilerplate for each asynchronous redux action, I will also offer &lt;a href="https://www.npmjs.com/package/fetch-action-creator"&gt;an open-source package&lt;/a&gt; that I've used almost religiously that will handle the action creation for you.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites 📍
&lt;/h2&gt;

&lt;p&gt;To enable asynchronous actions on your redux store, you will want to apply the &lt;a href="https://www.npmjs.com/package/redux-thunk"&gt;redux-thunk&lt;/a&gt; middleware.&lt;/p&gt;

&lt;p&gt;For API calls, I will be using the standardized &lt;code&gt;fetch&lt;/code&gt; API. If your target browser does not support the &lt;code&gt;fetch&lt;/code&gt; API, I would recommend a &lt;a href="https://www.npmjs.com/package/whatwg-fetch"&gt;&lt;code&gt;fetch&lt;/code&gt; polyfill&lt;/a&gt;. I also recommend using an &lt;a href="https://www.npmjs.com/package/abortcontroller-polyfill"&gt;&lt;code&gt;AbortController&lt;/code&gt; polyfill&lt;/a&gt; if you want to be able to abort your API calls, but not if you do not desire this feature. If you prefer an alternative to the &lt;code&gt;fetch&lt;/code&gt; API, such as &lt;code&gt;axios&lt;/code&gt; or &lt;code&gt;XMLHttpRequests&lt;/code&gt;, they are absolutely capable of handling asynchronous Redux state management, but my code examples will be based on the &lt;code&gt;fetch&lt;/code&gt; API.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is an asynchronous action? 🐌
&lt;/h2&gt;

&lt;p&gt;The first step is understanding what you are creating - unlike previous action creators that returned an action object that was immediately sent to the reducers, an asynchronous action is not an object but a function that is immediately invoked. That function accepts two parameters, each of which is a function. The first is the &lt;code&gt;dispatch&lt;/code&gt; function, used to dispatch an action; the second is a &lt;code&gt;getState&lt;/code&gt; function, used to get the current Redux state.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Synchronously add an employee.&lt;/span&gt;
&lt;span class="c1"&gt;// addEmployee("Bob");&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;addEmployee&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ADD_EMPLOYEE&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;name&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;



&lt;span class="c1"&gt;// Asynchronously add an employee.&lt;/span&gt;
&lt;span class="c1"&gt;// addEmployeeAsync("Bob")&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;addEmployeeAsync&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="c1"&gt;// Since the return value of this action creator&lt;/span&gt;
  &lt;span class="c1"&gt;//   accepts dispatch as a parameter instead of&lt;/span&gt;
  &lt;span class="c1"&gt;//   returning what is to be dispatched,&lt;/span&gt;
  &lt;span class="c1"&gt;//   I may dispatch at my leisure and as many times as I want.&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;getState&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;// I want to immediately and synchronously add the employee.&lt;/span&gt;
    &lt;span class="nx"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;addEmployee&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="c1"&gt;// I want to asynchronously remove the employee.&lt;/span&gt;
    &lt;span class="c1"&gt;// This is a second action in a single action creator.&lt;/span&gt;
    &lt;span class="nx"&gt;setTimeout&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;dispatch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;removeEmployee&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="mi"&gt;0&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// I want to asynchronously re-add that employee after 5 seconds.&lt;/span&gt;
    &lt;span class="c1"&gt;// This is a third action in a single action creator.&lt;/span&gt;
    &lt;span class="nx"&gt;setTimeout&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;dispatch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;addEmployee&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="mi"&gt;5000&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;Normally, when your action creator returns an object, that object gets passed to your reducer. Now, when your action creators return functions, the redux-thunk middleware will immediately invoke that function instead of passing it to the reducer. That function can do anything. Unlike other action creators, this function &lt;em&gt;does not&lt;/em&gt; return the action object. Using the dispatch parameter, you can dispatch action objects to the reducer. The upside of manually dispatching them instead of returning them is that you can dispatch as many actions as needed, such as one for each state in an API call, despite having only dispatched &lt;em&gt;one&lt;/em&gt; action creator.&lt;/p&gt;

&lt;p&gt;In summation, your components dispatch one asynchronous action (in this case, &lt;code&gt;addEmployeeAsync&lt;/code&gt;). That asynchronous action in turn dispatches multiple actions (&lt;code&gt;addEmployee&lt;/code&gt;, &lt;code&gt;removeEmployee&lt;/code&gt;, then &lt;code&gt;addEmployee&lt;/code&gt; again). There is no reason to add, remove, then add again. It’s just an example of your freedom in design.&lt;/p&gt;

&lt;h2&gt;
  
  
  The States of the Fetch API 🎌
&lt;/h2&gt;

&lt;p&gt;Now that we know how to create an action that can dispatch multiple states over time, let’s identify and dispatch the states of a fetch request.&lt;/p&gt;

&lt;p&gt;The first state of an API request is &lt;em&gt;requested&lt;/em&gt; (loading). The request has been dispatched, but we have not yet received a response.&lt;/p&gt;

&lt;p&gt;The subsequent state of an API request is either &lt;em&gt;received&lt;/em&gt; (success) or &lt;em&gt;rejected&lt;/em&gt; (error) depending on the response from the server.&lt;/p&gt;

&lt;p&gt;The final, potential state of an API request is &lt;em&gt;aborted&lt;/em&gt; (cancelled) for if you or the user terminates the request before receiving a response.&lt;/p&gt;

&lt;p&gt;For each API endpoint required to power your application, an initial Redux state may look something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;myApiData&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;abortController&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;aborted&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;error&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;loading&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;response&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You will want an action for each of these states, since each of the API request’s states should be reflected in your application.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// When the API is requested,&lt;/span&gt;
&lt;span class="c1"&gt;//   this action is sent to the reducer.&lt;/span&gt;
&lt;span class="c1"&gt;// The abortController tied to the request,&lt;/span&gt;
&lt;span class="c1"&gt;//   so passed to the request action creator.&lt;/span&gt;
&lt;span class="c1"&gt;// You may store it in your redux state for future use.&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;requestMyApi&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;abortController&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;REQUEST_MY_API&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;abortController&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// When the API responds,&lt;/span&gt;
&lt;span class="c1"&gt;//   this action is sent to the reducer.&lt;/span&gt;
&lt;span class="c1"&gt;// It includes the response, which is probably&lt;/span&gt;
&lt;span class="c1"&gt;//   the entire point of this process.&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;receiveMyApi&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;RECEIVE_MY_API&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;response&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// When the API fails to respond,&lt;/span&gt;
&lt;span class="c1"&gt;//   this action is sent to the reducer.&lt;/span&gt;
&lt;span class="c1"&gt;// The provided error is included, which can&lt;/span&gt;
&lt;span class="c1"&gt;//   be used to display to users or debug.&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;rejectMyApi&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;err&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;REJECT_MY_API&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;err&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// When the API request has been aborted or cancelled,&lt;/span&gt;
&lt;span class="c1"&gt;//   this action is sent to the reducer.&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;abortMyApi&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ABORT_MY_API&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The Abort Action 🙅
&lt;/h2&gt;

&lt;p&gt;In order for the API request to notify the developer that it has been cancelled, it must be passed an &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal"&gt;&lt;code&gt;AbortSignal&lt;/code&gt;&lt;/a&gt; at instantiation. Despite this not being the first action dispatched, it will be the first we write, because it must be written before the API request is initialized.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;abortController&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Since AbortController is not well-supported yet, we check for its existence.&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;AbortController&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;undefined&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;abortController&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;AbortController&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="nx"&gt;signal&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;abortController&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;abort&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;dispatch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;abortMyApi&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;If the browser supports it, we create an &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/AbortController"&gt;&lt;code&gt;AbortController&lt;/code&gt;&lt;/a&gt;, and we add a listener for the abort signal. When the abort signal event occurs, we dispatch the abort action. The &lt;code&gt;AbortController&lt;/code&gt; will later be passed as a part of the request action. This allows you to store it in your redux state, giving your components and users access to manually abort an API request via the controller.&lt;/p&gt;

&lt;p&gt;When a &lt;code&gt;ABORT_MY_API&lt;/code&gt; action is received by your reducer, you can manipulate the state accordingly: It is no longer loading, there was no response, there was no error, and it was aborted. You may prefer replacing the aborted flag with an error string to simplify your logic, if that matches your use case. I would suggest against it, however, due to such logic differences as “Can the user re-request the payload if they aborted the previous one? If an error occurred during the previous one?”&lt;/p&gt;

&lt;h2&gt;
  
  
  The Request Action 📞
&lt;/h2&gt;

&lt;p&gt;You should use the &lt;em&gt;request&lt;/em&gt; action to enable a loading view. Consider using a loading animation or text to notify your user that &lt;em&gt;something is happening&lt;/em&gt;. The feedback goes a long way in making your application feel responsive. The &lt;code&gt;REQUEST_MY_API&lt;/code&gt; action will toggle the &lt;code&gt;state.myApi.loading&lt;/code&gt; from false to true. Your components can now respond to this redux state accordingly. Components that depend on the response from my API can display that they are in the process of loading.&lt;/p&gt;

&lt;p&gt;Since a request is instantiated immediately, you can dispatch that action immediately in your asynchronous action creator: &lt;code&gt;dispatch(requestMyApi(abortController))&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Since we have told the reducer that we have requested the data, we should actually request it: &lt;code&gt;fetch(URL, { signal })&lt;/code&gt;. You can adjust your fetch options as needed. The &lt;code&gt;signal&lt;/code&gt; is the one created as a part of the abort handler above.&lt;/p&gt;

&lt;p&gt;It takes more than just requesting the data, we also need to handle the response.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Response Action 🙌
&lt;/h2&gt;

&lt;p&gt;Once the fetch Promise resolves, we can take that response, parse it accordingly (as text or JSON), and send the parsed data to the reducer, making it accessible to your components.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="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="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;signal&lt;/span&gt; &lt;span class="p"&gt;})&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;response&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;// If this payload is JSON, use this:&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;response&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="c1"&gt;// If this payload is not JSON, use this:&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&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;// Now that we've parsed the response,&lt;/span&gt;
    &lt;span class="c1"&gt;//   we can send it to the reducer.&lt;/span&gt;
    &lt;span class="nx"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;receiveMyApi&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The Error Action ❌
&lt;/h2&gt;

&lt;p&gt;The error action is even easier. Since we’re working with promises, we just &lt;code&gt;catch&lt;/code&gt;!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="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="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;signal&lt;/span&gt; &lt;span class="p"&gt;})&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;parseData&lt;/span&gt;&lt;span class="p"&gt;)&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;receiveMyApi&lt;/span&gt;&lt;span class="p"&gt;)&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;dispatch&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&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;// An error occurred at some point in this Promise.&lt;/span&gt;
    &lt;span class="c1"&gt;// Pass the error to the reducer.&lt;/span&gt;
    &lt;span class="nx"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;rejectMyApi&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  Considerations 🤔
&lt;/h2&gt;

&lt;p&gt;There is more complex error-handling involved if your API is &lt;em&gt;successfully responding&lt;/em&gt; with &lt;em&gt;error status codes&lt;/em&gt; and an error message as a part of the parsed payload. I won’t cover that case in detail here, because it does not apply to all APIs, but you can see how I handled it in the &lt;a href="https://github.com/CharlesStover/fetch-action-creator/blob/master/fetch-action-creator.ts#L136"&gt;source code of this package&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;You also have the power of the &lt;code&gt;getState&lt;/code&gt; function. You may use the current redux state to modify (or even ignore) your current fetch request. Depending on the scenario and action, sometimes I will get the current state to see if the request is already loading or has responded in the past. If it has, I just don’t fetch. The async action was clearly dispatched in error, so I can safely ignore it — I already have the data, so fetching it will provide me with no benefit.&lt;/p&gt;

&lt;h2&gt;
  
  
  Can’t Most of This Be Automated? 🤖
&lt;/h2&gt;

&lt;p&gt;Yes! The &lt;a href="https://www.npmjs.com/package/fetch-action-creator"&gt;&lt;code&gt;fetch-action-creator&lt;/code&gt; package&lt;/a&gt; does all of the above so that you don’t have to copy-paste this boilerplate for every API action. Every API call will do the same series of things: create an abort controller and signal, fetch the request, parse the response, check the response for error status codes, and dispatch an action for each of the four states involved in the process.&lt;/p&gt;

&lt;p&gt;If I love anything, it’s &lt;a href="https://en.wikipedia.org/wiki/Don%27t_repeat_yourself"&gt;DRY code&lt;/a&gt;! That’s why I use and recommend a function that will do all of these things for you. All you are left to do is provide the differences between any two given API calls: a unique identifier, the URL, and the fetch options.&lt;/p&gt;

&lt;p&gt;Just &lt;code&gt;npm install fetch-action-creator&lt;/code&gt; or &lt;code&gt;yarn add fetch-action-creator&lt;/code&gt;!&lt;/p&gt;

&lt;h2&gt;
  
  
  fetch-action-creator 🐶🎾
&lt;/h2&gt;

&lt;p&gt;Be sure to understand the difference between an &lt;em&gt;action&lt;/em&gt; and an &lt;em&gt;action creator&lt;/em&gt;. The &lt;a href="https://www.npmjs.com/package/fetch-action-creator"&gt;&lt;code&gt;fetch-action-creator&lt;/code&gt; package&lt;/a&gt; does not return an action creator. It &lt;em&gt;is&lt;/em&gt; an action creator, so it returns an asynchronous action, meaning it returns the &lt;code&gt;(dispatch, getState) =&amp;gt; {}&lt;/code&gt; function.&lt;/p&gt;

&lt;p&gt;Your action creator will look something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;fetchActionCreator&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;fetch-action-creator&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fetchMyApi&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
  &lt;span class="nx"&gt;fetchActionCreator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;MY_API&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;https://path.to/api&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="c1"&gt;// fetch options, if any&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;'MY_API'&lt;/code&gt; string is used to generate the Redux action types: &lt;code&gt;'REQUEST_MY_API'&lt;/code&gt;, &lt;code&gt;'RESOLVE_MY_API'&lt;/code&gt;, &lt;code&gt;'REJECT_MY_API'&lt;/code&gt;, and &lt;code&gt;'ABORT_MY_API'&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Your React components will only bind and call the &lt;code&gt;fetchMyApi&lt;/code&gt; action creator, which notably has no parameters in this example.&lt;/p&gt;

&lt;p&gt;You can use parameters to customize your fetch actions. It’s a little more work to extend your actions inline, but the payoff in extensibility is huge.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;fetchActionCreator&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;fetch-action-creator&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// We now call fetchAddEmployee("Bob")&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fetchAddEmployee&lt;/span&gt; &lt;span class="o"&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="nx"&gt;fetchActionCreator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ADD_EMPLOYEE&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;https://path.to/employees&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

    &lt;span class="c1"&gt;// POST Bob&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;

    &lt;span class="c1"&gt;// For each action, merge with object { name }&lt;/span&gt;
    &lt;span class="c1"&gt;//   to add a name property containing&lt;/span&gt;
    &lt;span class="c1"&gt;//   employee's name to the action object.&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;onAbort&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="na"&gt;onReject&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="na"&gt;onRequest&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="na"&gt;onResolve&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can check out &lt;a href="https://github.com/CharlesStover/fetch-action-creator/"&gt;the documentation&lt;/a&gt; for advanced options on mutating the Redux actions.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;fetch-action-creator&lt;/code&gt; package is &lt;a href="https://github.com/CharlesStover/fetch-action-creator/"&gt;open-source on GitHub&lt;/a&gt;. Pull requests are welcome!&lt;/p&gt;

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

&lt;p&gt;If you liked this article, feel free to give it a heart or unicorn. It’s quick, it’s easy, and it’s free! If you have any questions or relevant commentary, please leave them in the comments below.&lt;/p&gt;

&lt;p&gt;To read more of my columns, you may follow me on &lt;a href="https://www.linkedin.com/in/charles-stover"&gt;LinkedIn&lt;/a&gt;, &lt;a href="https://medium.com/@Charles_Stover"&gt;Medium&lt;/a&gt;, and &lt;a href="https://twitter.com/CharlesStover"&gt;Twitter&lt;/a&gt;, or &lt;a href="https://charlesstover.com/"&gt;check out my portfolio on CharlesStover.com&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>react</category>
      <category>reactnative</category>
      <category>redux</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Fixing React Native WebView’s postMessage for iOS</title>
      <dc:creator>Charles Stover</dc:creator>
      <pubDate>Tue, 04 Jun 2019 20:00:32 +0000</pubDate>
      <link>https://forem.com/charlesstover/fixing-react-native-webview-s-postmessage-for-ios-a68</link>
      <guid>https://forem.com/charlesstover/fixing-react-native-webview-s-postmessage-for-ios-a68</guid>
      <description>&lt;p&gt;In 2016, GitHub user Robert Roskam (raiderrobert) &lt;a href="https://github.com/facebook/react-native/issues/10865"&gt;opened an issue&lt;/a&gt; on the React Native repository reporting the error “&lt;em&gt;Setting onMessage on a WebView overrides existing values of window.postMessage, but a previous value was defined&lt;/em&gt;”. In the two years since then, nothing has been done to resolve it within the internal React Native implementation of WebView.&lt;/p&gt;

&lt;p&gt;The React Native community has &lt;a href="https://github.com/react-native-community/react-native-webview"&gt;forked WebView&lt;/a&gt; specifically to maintain it as a third party package and fix many of these ongoing issues. However, in order to implement these third party packages, you must be able to link React Native packages — &lt;code&gt;react-native link react-native-webview&lt;/code&gt;. If you are able and willing to do this, your problem is solved. The installation instructions for the community edition of WebView are as simple as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;yarn add https://github.com/react-native-community/react-native-webview
react-native link react-native-webview 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; In order to &lt;code&gt;react-native link ...&lt;/code&gt;, you must first &lt;code&gt;yarn global add react-native&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Unfortunately, if you are unable or unwilling to do this, there has simply been no solution to this problem. For years!&lt;/p&gt;

&lt;p&gt;Users of Expo, for example, would have to eject their project and write their own native, non-JavaScript implementation of features. Expo will, theoretically, be using these community edition packages in future releases; but with a launch window only weeks away, my team and myself were not willing to wait.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Solution 💡
&lt;/h2&gt;

&lt;p&gt;If you care more about getting this solved &lt;em&gt;right now&lt;/em&gt; than how it works, this section is for you.&lt;/p&gt;

&lt;p&gt;Either &lt;code&gt;npm install rn-webview&lt;/code&gt; or &lt;code&gt;yarn add rn-webview&lt;/code&gt; to add the &lt;a href="https://www.npmjs.com/package/rn-webview"&gt;&lt;code&gt;rn-webview&lt;/code&gt; package&lt;/a&gt; to your project.&lt;/p&gt;

&lt;p&gt;Wherever you are using &lt;code&gt;import { WebView } from 'react-native'&lt;/code&gt;, simply replace it with &lt;code&gt;import WebView from 'rn-webview'&lt;/code&gt;. Then just use the new WebView component as you would the React Native internal implementation, including the use of the &lt;code&gt;onMessage&lt;/code&gt; prop. The &lt;code&gt;rn-webview&lt;/code&gt; package is just a wrapper for the internal React Native implementation that intercepts messages through a different channel than the internal &lt;code&gt;onMessage&lt;/code&gt; prop, but handles it with its own &lt;code&gt;onMessage&lt;/code&gt; prop, giving the illusion that you are actually using the internal &lt;code&gt;onMessage&lt;/code&gt; with expected results.&lt;/p&gt;

&lt;h2&gt;
  
  
  Caveats 🤕
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;rn-webview&lt;/code&gt; package works by directing &lt;code&gt;window.postMessage&lt;/code&gt; traffic to &lt;code&gt;history.pushState&lt;/code&gt; instead. While React Native’s iOS implementation cannot handle &lt;code&gt;window.postMessage&lt;/code&gt; correctly, it can handle navigation state changes. Because of this, the navigation state change event is the channel through which messages are transferred between the WebView and the native application.&lt;/p&gt;

&lt;p&gt;If manipulation of the history state is an important aspect of your application, this solution may not suit your needs. Feel free to &lt;a href="https://github.com/CharlesStover/react-native-web-view"&gt;fork the project on GitHub&lt;/a&gt; to offer alternative solutions.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Implementation 🔨
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Export 🚢
&lt;/h3&gt;

&lt;p&gt;First and foremost, the &lt;code&gt;ref&lt;/code&gt; prop of WebView is a particularly important one. Because of this, we don’t want the user to lose access to it. We start the package with a &lt;code&gt;forwardRef&lt;/code&gt; implementation, where &lt;code&gt;WebViewPostMessage&lt;/code&gt; is the class name used for this package.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;forwardRef&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;WebViewPostMessage&lt;/span&gt;
    &lt;span class="p"&gt;{...&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nx"&gt;forwardedRef&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Render 🎨
&lt;/h3&gt;

&lt;p&gt;The output of this component is going to be the React Native internal implementation of WebView, with a few tweaks. We aren’t going to give it the &lt;code&gt;forwardedRef&lt;/code&gt; prop, because that is only used to give the parent access to the &lt;code&gt;ref&lt;/code&gt; and is totally meaningless to the internal WebView. Most importantly, we aren’t going to give it the &lt;code&gt;onMessage&lt;/code&gt; prop, because that is the source of all of our problems — it’s not supported by iOS!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;render&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;props&lt;/span&gt; &lt;span class="o"&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;props&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="k"&gt;delete&lt;/span&gt; &lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;forwardedRef&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;delete&lt;/span&gt; &lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onMessage&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;WebView&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;props&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="nx"&gt;onNavigationStateChange&lt;/span&gt;&lt;span class="o"&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;handleNavigationStateChange&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="o"&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;handleRef&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="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 have a custom navigation state change listener, because that is the channel through which we will be listening for messages.&lt;/p&gt;

&lt;p&gt;We have a custom ref handler, because we both 1) need access to it inside this component and 2) need to pass the ref back to the parent container via the &lt;code&gt;forwardedRef&lt;/code&gt; prop.&lt;/p&gt;

&lt;h3&gt;
  
  
  Ref 👋
&lt;/h3&gt;

&lt;p&gt;When the internal WebView gives us its ref, we store it on the instance (&lt;code&gt;this.ref = ref&lt;/code&gt;) for use later. If the parent requested the ref as well, we forward it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;handleRef&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ref&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ref&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="c1"&gt;// If the caller also wants this ref, pass it along to them as well.&lt;/span&gt;
  &lt;span class="k"&gt;if&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;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;forwardedRef&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;forwardedRef&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ref&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;h3&gt;
  
  
  Inject window.postMessage 💉
&lt;/h3&gt;

&lt;p&gt;Now, a custom implementation of &lt;code&gt;window.postMessage&lt;/code&gt; needs to exist on any page in the WebView. Whenever the navigation state changes, if it has finished loading, we inject JavaScript into it to override what &lt;code&gt;window.postMessage&lt;/code&gt; does.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;handleNavigationStateChange&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="cm"&gt;/* We'll do something here later. */&lt;/span&gt;

  &lt;span class="c1"&gt;// If this navigation state change has completed, listen for messages.&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;loading&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&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;ref&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;injectJavaScript&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;injectPostMessage&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="cm"&gt;/* We'll do something here later. */&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;I defined and &lt;code&gt;importedinjectPostMessage&lt;/code&gt; from a different file for readability.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="s2"&gt;`
(function() {
  var EMPTY_STATE = Object.create(null);
  var escape = function(str) {
    return str.replace(/'/g, '\\\\\'');
  };
  var postMessage = window.postMessage;
  window.postMessage = function() {
    if (postMessage) {
      postMessage.apply(window, arguments);
    }
    history.pushState(
      EMPTY_STATE,
      document.title,
      location.href +
      '#window.postMessage(\\\'' +
      escape(arguments[0]) +
      '\\\')'
    );
  };
})();
`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;It is an &lt;a href="https://en.wikipedia.org/wiki/Immediately-invoked_function_expression"&gt;immediately-invoked function expression&lt;/a&gt; to make sure none of our variables conflict with the web page.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;EMPTY_STATE&lt;/code&gt; is what is pushed to history, since we won’t be using a state object for our event listener.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;escape&lt;/code&gt; function escapes apostrophes in a string so that we can place that string in apostrophes. Since the navigation state that we push is not real JavaScript and won’t be passed through any sort of JavaScript interpreter, this step is not exactly necessary. It just allows the state we push to more closely mimic real JavaScript.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;postMessage&lt;/code&gt; variable checks to see if a &lt;code&gt;postMessage&lt;/code&gt; function already exists. If so, we’ll want to execute it also during any &lt;code&gt;window.postMessage&lt;/code&gt; calls.&lt;/p&gt;

&lt;p&gt;We define our own &lt;code&gt;window.postMessage&lt;/code&gt; function. The first thing it does is executes the previous &lt;code&gt;window.postMessage&lt;/code&gt; function, if it existed.&lt;/p&gt;

&lt;p&gt;Next, we push to the history state. We have no state object, so we use the aforementioned empty one. The title of the document is not changing, so we just use the current one. The location of the document is also not changing per se: we are merely appending a hash.&lt;/p&gt;

&lt;p&gt;That hash, which we’ll be listening for later, is &lt;code&gt;window.postMessage('the message')&lt;/code&gt;. It looks like JavaScript, by design, but is not going to be evaluated by any real JavaScript interpreter. We just need a unique hash that won’t collide with real, in-document hashes.&lt;/p&gt;

&lt;h3&gt;
  
  
  postMessage Listener 📬
&lt;/h3&gt;

&lt;p&gt;Now that we have our own &lt;code&gt;window.postMessage&lt;/code&gt; event emitter, we need to listen for it. This is the code that goes at the top of the &lt;code&gt;handleNavigationStateChange&lt;/code&gt; method.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;postMessage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;e&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;match&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;\#&lt;/span&gt;&lt;span class="sr"&gt;window&lt;/span&gt;&lt;span class="se"&gt;\.&lt;/span&gt;&lt;span class="sr"&gt;postMessage&lt;/span&gt;&lt;span class="se"&gt;\(&lt;/span&gt;&lt;span class="sr"&gt;'&lt;/span&gt;&lt;span class="se"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;.+&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="sr"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\)&lt;/span&gt;&lt;span class="sr"&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;postMessage&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;loading&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&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;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onMessage&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onMessage&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;nativeEvent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;unescape&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;postMessage&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;We check if the new URL matches the &lt;code&gt;postMessage&lt;/code&gt; hash we defined earlier. If it does, we’re going to &lt;code&gt;return&lt;/code&gt; so that the rest of the navigation state change event listener doesn’t fire. This is a message event, not a navigation state change (technicalities aside).&lt;/p&gt;

&lt;p&gt;Each &lt;code&gt;postMessage&lt;/code&gt; event will fire the navigation state change twice — once for &lt;code&gt;loading: true&lt;/code&gt; and one, almost immediately after, for &lt;code&gt;loading: false&lt;/code&gt;. We are only listening for the &lt;code&gt;loading: true&lt;/code&gt; event, because it occurs first. The &lt;code&gt;loading: false&lt;/code&gt; event is ignored, because it is just a duplicate.&lt;/p&gt;

&lt;p&gt;Only if the parent component passed an &lt;code&gt;onMessage&lt;/code&gt; event handler, we call that handler with a mock event that contains the message. We unescape the message before passing it, because we escaped the apostrophes earlier.&lt;/p&gt;

&lt;p&gt;The unescape function is defined at the top of the document, because it is constant (does not depend on the instance) and does not need to be a method of the component. You may import it if you prefer to code split it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;unescape&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;str&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
  &lt;span class="nx"&gt;str&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="sr"&gt;'/g&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\'&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  onNavigationStateChange 🕵
&lt;/h3&gt;

&lt;p&gt;The above covers everything we need for intercepting &lt;code&gt;window.postMessage&lt;/code&gt; and handling it with one’s own &lt;code&gt;onMessage&lt;/code&gt; event listener. Our original problem is already solved — &lt;code&gt;onMessage&lt;/code&gt; works with this WebView. However, since we have overwritten the internal &lt;code&gt;onNavigationStateChange&lt;/code&gt; listener, the parent is no longer receiving navigation state change events.&lt;/p&gt;

&lt;p&gt;At the bottom of the &lt;code&gt;handleNavigationStateChange&lt;/code&gt; event listener, add the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;if&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;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onNavigationStateChange&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onNavigationStateChange&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;If the parent has included an &lt;code&gt;onNavigationStateChange&lt;/code&gt; prop, call it, and give it this navigation state change event.&lt;/p&gt;

&lt;p&gt;The empty return is simply personal preference — I don’t believe functions should conditionally return, even if it’s functionally equivalent to an implicit return.&lt;/p&gt;

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

&lt;p&gt;As a reminder, you can include the component just outlined by installing the &lt;a href="https://www.npmjs.com/package/rn-webview"&gt;&lt;code&gt;rn-webview&lt;/code&gt; package&lt;/a&gt; from NPM. You may also fork it on GitHub.&lt;/p&gt;

&lt;p&gt;If you liked this article, feel free to give it a heart or unicorn. It’s quick, it’s easy, and it’s free! If you have any relevant commentary, please leave it in the comments below.&lt;/p&gt;

&lt;p&gt;To read more of my columns, you may follow me on &lt;a href="https://www.linkedin.com/in/charles-stover"&gt;LinkedIn&lt;/a&gt;, &lt;a href="https://medium.com/@Charles_Stover"&gt;Medium&lt;/a&gt;, and &lt;a href="https://twitter.com/CharlesStover"&gt;Twitter&lt;/a&gt;, or &lt;a href="https://charlesstover.com/"&gt;check out my portfolio on CharlesStover.com&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>reactnative</category>
      <category>ios</category>
      <category>react</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Are you underqualified to apply to a software development position?</title>
      <dc:creator>Charles Stover</dc:creator>
      <pubDate>Sun, 02 Jun 2019 22:12:25 +0000</pubDate>
      <link>https://forem.com/charlesstover/are-you-under-qualified-to-apply-to-a-software-development-position-1kd4</link>
      <guid>https://forem.com/charlesstover/are-you-under-qualified-to-apply-to-a-software-development-position-1kd4</guid>
      <description>&lt;p&gt;Reddit user &lt;a href="https://www.reddit.com/user/orduk"&gt;orduk&lt;/a&gt; asked, “&lt;a href="https://www.reddit.com/r/webdev/comments/blab5o/how_under_qualified_were_you_when_you_applied_for/"&gt;How under qualified were you when you applied for your current position?&lt;/a&gt;”&lt;/p&gt;

&lt;p&gt;There are a lot of misconceptions about what constitutes as “qualified.” Job postings are notorious for having laughable minimum requirements: more years of experience using a language than it has existed, senior level requirements for junior positions, or years of experience expected of fresh college graduates. It’s no surprise than many juniors feel the “you need experience to get experience” barrier is all too real.&lt;/p&gt;

&lt;p&gt;I wanted to make one thing clear:&lt;/p&gt;

&lt;h2&gt;
  
  
  You should always be under qualified. 🎯
&lt;/h2&gt;

&lt;p&gt;The top comment, by user &lt;a href="https://www.reddit.com/user/vidro3"&gt;vidro3&lt;/a&gt;, to orduk’s question is a great reflection of the developer experience: “Bold assumption that I’m now qualified for my current position.”&lt;/p&gt;

&lt;p&gt;Your job pays you twice — once with money, and once with knowledge. This does not only apply to juniors; it applies to seniors as well. If you are only getting paid one of these ways, &lt;em&gt;you are underpaid&lt;/em&gt;. If you are not growing at your job, you are being held back from advancing your career. By definition, then, you must be “under qualified” or else be stagnant in your personal growth.&lt;/p&gt;

&lt;p&gt;This changes the perception of qualified. If you expect to grow at your job, and your company expects you to grow at your job, then you cannot have perfected or know all aspects of your job. You must be hired at a level where you can grow: you must be &lt;em&gt;under qualified&lt;/em&gt;. This really just means that under qualified is the qualification level.&lt;/p&gt;

&lt;h2&gt;
  
  
  Red Flags 🚩
&lt;/h2&gt;

&lt;p&gt;Good tech companies will hire “under qualified” individuals because that individual has potential for growth. It is a red flag when a tech company wants an overqualified individual. They don’t want the individual to learn anything new or better themselves. “This is the level you are hired at, and this is all you will ever be. Don’t expect a raise or a promotion, because your job is not going to change, and your performance will never improve.”&lt;/p&gt;

&lt;p&gt;You should &lt;em&gt;always&lt;/em&gt; be underqualified for any job to which you apply. The biggest sell of a candidate is not their encyclopedic knowledge, but their eagerness and ability to learn what they don’t know. If an employer invests in you as a junior, they hope to eventually have a senior with company loyalty.&lt;/p&gt;

&lt;h2&gt;
  
  
  Underqualified is Qualified 💼
&lt;/h2&gt;

&lt;p&gt;Do not ever treat a “minimum requirements” as a wall. Apply anyway, if only for the interview experience. I’ve been a web developer for 17 years now, and I still rarely meet all the minimum requirements.&lt;/p&gt;

&lt;p&gt;To answer orduk’s question, I am currently a front end engineer for the largest cloud service provider in the world. Outside of OneDrive for personal file storage, I had never used a cloud service a day in my life. I had not even used services that would have aided my development career; I always hosted my applications myself. I had no experience with serverless. I had not studied system design until two weeks before my interview — because they told me to study it for my interview. I did not know how most cloud services worked, but I am learning on the job, and the knowledge I am gaining, in addition to my paycheck, is that additional compensation that will allow me to grow as a person, as a developer, and in my career.&lt;/p&gt;

&lt;h2&gt;
  
  
  It’s about selling yourself. 💸
&lt;/h2&gt;

&lt;p&gt;Being a self-taught front end engineer, not having a degree was one of my biggest hurdles. It took a long time for me to learn how to sell myself. I knew a great deal, I had great learning potential, but I didn’t have the &lt;em&gt;confidence&lt;/em&gt; or &lt;em&gt;soft skills&lt;/em&gt; to know how to convey that potential in an interview. I read “college degree” on minimum requirements and gave up. If only I knew then what I know now, I would be so much further in my career! Going to interviews for the sake of learning how to interview was one of the best things I could have done. Even when I was rejected, I learned what was in demand from those interviews, and I learned those things. Then, they stopped caring about my degree and started caring that I was A) passionate, B) eager to learn, and C) dove deep into material for a below-surface-level understanding.&lt;/p&gt;

&lt;p&gt;Minimum requirements are not minimum requirements. Underqualified is expected. Soft skills are the greatest asset, not a degree or encyclopedic knowledge. You need experience to get experience is true, but knowing how to sell your self-taught or practice experiences as &lt;em&gt;real&lt;/em&gt; experience is the confidence that can come from practice interviewing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Confidence Speaks Volumes 🧠
&lt;/h2&gt;

&lt;p&gt;As an example, a not-so-confident statement would be, “I published some of my JavaScript to NPM.” The interviewer knows that you know JavaScript and NPM. That’s okay.&lt;/p&gt;

&lt;p&gt;A confident way of saying the same thing would be, “I designed a reusable component that was extensible to all customer use cases. With GitHub Issues, I engaged customers to meet their needs, prioritized features, and maintain my service to them.” The interviewer knows that you can communicate technical ideas to users who are not on the same level of expertise, can design code that works across teams, can account for edge cases, can prioritize features, and can offer long-term support and maintenance. 👌&lt;/p&gt;

&lt;p&gt;I am talking about the same code in both cases. Both statements come from the same level of qualification. One is &lt;em&gt;selling myself&lt;/em&gt; and the other is &lt;em&gt;selling myself short&lt;/em&gt;. Practice interviews worked wonders for me. I was able to learn what companies wanted (“Discuss a time you had a conflict with a superior and how you resolved it.”), practiced talking about my skills at home without the pressure or anxiety, then interviewed again with confidence. Rinse and repeat.&lt;/p&gt;

&lt;h2&gt;
  
  
  Interviewing is Win-Win 🏆
&lt;/h2&gt;

&lt;p&gt;Interviewing is not a test where you fail for not getting hired. If you do not get hired, &lt;em&gt;you still learned something&lt;/em&gt;. You should be &lt;em&gt;using&lt;/em&gt; the company when you interview. Determine what is important to them. You should leave the interview more knowledgeable than you entered. You are a better developer after failing an interview because you know something you didn’t know the day before — you know some in demand tech stacks, you know some soft skills that are higher priority, and hopefully you will know what steps to take next to acquire any skills you are lacking.&lt;/p&gt;

&lt;p&gt;Keep at it and see the opportunity in every obstacle.&lt;/p&gt;

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

&lt;p&gt;If you liked this article, feel free to give it a heart or a unicorn. It’s quick, it’s easy, and it’s free! If you have any questions or great commentary, please leave them in the comments below.&lt;/p&gt;

&lt;p&gt;To read more of my columns, you may follow me on &lt;a href="https://www.linkedin.com/in/charles-stover"&gt;LinkedIn&lt;/a&gt;, &lt;a href="https://medium.com/@Charles_Stover"&gt;Medium&lt;/a&gt;, and &lt;a href="https://twitter.com/CharlesStover"&gt;Twitter&lt;/a&gt;, or &lt;a href="https://charlesstover.com/"&gt;check out my portfolio on CharlesStover.com&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>career</category>
      <category>webdev</category>
      <category>beginners</category>
      <category>discuss</category>
    </item>
    <item>
      <title>Cache your React event listeners to improve performance.</title>
      <dc:creator>Charles Stover</dc:creator>
      <pubDate>Sun, 02 Jun 2019 20:41:40 +0000</pubDate>
      <link>https://forem.com/charlesstover/cache-your-react-event-listeners-to-improve-performance-3i76</link>
      <guid>https://forem.com/charlesstover/cache-your-react-event-listeners-to-improve-performance-3i76</guid>
      <description>&lt;p&gt;An under-appreciated concept in JavaScript is how objects and functions are &lt;em&gt;references&lt;/em&gt;, and that directly impacts React performance. If you were to create two functions that are completely identical, they are still not equal. Try for yourself:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;functionOne&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;alert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Hello world!&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;const&lt;/span&gt; &lt;span class="nx"&gt;functionTwo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;alert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Hello world!&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;functionOne&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;functionTwo&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But check out the difference if you assign a variable to an already-existing function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;functionThree&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;alert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Hello world!&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;const&lt;/span&gt; &lt;span class="nx"&gt;functionFour&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;functionThree&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;functionThree&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;functionFour&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Objects work the same way.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;object1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;object2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;object3&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;object1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;object1&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;object2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// false&lt;/span&gt;
&lt;span class="nx"&gt;object1&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;object3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you have experience in other languages, you may be familiar with &lt;em&gt;pointers&lt;/em&gt;. What is happening here is that each time you create an object, you are allocating some amount of memory on the device. When I said that &lt;code&gt;object1 = {}&lt;/code&gt;, I have created a chunk of bytes in the user’s RAM that is dedicated specifically to &lt;code&gt;object1&lt;/code&gt;. It is fair to imagine &lt;code&gt;object1&lt;/code&gt; as an address that contains where in RAM its key-value pairs are located. When I said &lt;code&gt;object2 = {}&lt;/code&gt;, I created a &lt;em&gt;different&lt;/em&gt; chunk of bytes in the user’s RAM that is dedicated specifically to &lt;code&gt;object2&lt;/code&gt;. Does the &lt;em&gt;address&lt;/em&gt; of &lt;code&gt;object1&lt;/code&gt; match the address of &lt;code&gt;object2&lt;/code&gt;? No. That is why the equality check for the two variables does not pass. Their key-value pairs may be exactly the same, but their addresses in memory are different, and that is what is being compared.&lt;/p&gt;

&lt;p&gt;When I assigned &lt;code&gt;object3 = object1&lt;/code&gt;, I am assigning the value of &lt;code&gt;object3&lt;/code&gt; to be the address of &lt;code&gt;object1&lt;/code&gt;. It is not a &lt;em&gt;new&lt;/em&gt; object. It is that same location in memory. You can verify this like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;object1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;object3&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;object1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;object3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;object1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, I created an object in memory and assigned it to &lt;code&gt;object1&lt;/code&gt;. I then assigned &lt;code&gt;object3&lt;/code&gt; to that same address in memory. By mutating &lt;code&gt;object3&lt;/code&gt;, I have changed the value at that location in memory, meaning &lt;em&gt;all other references to that location in memory change as well&lt;/em&gt;. &lt;code&gt;object1&lt;/code&gt;, which still points to that location in memory, now has a changed value.&lt;/p&gt;

&lt;p&gt;This is a very common error for junior developers to make, and likely warrants an in-depth tutorial of its own; but this particular tutorial is about React performance, which may be compromised even by developers with more seniority who have simply not considered the implications of variable references.&lt;/p&gt;

&lt;p&gt;What does this have to do with React? React has an intelligent way of saving processing time to boost performance: If a PureComponent’s props and state have not changed, then the output of &lt;code&gt;render&lt;/code&gt; must not have changed either. Clearly, if all things are equal, nothing has changed. If nothing has changed, &lt;code&gt;render&lt;/code&gt; must return the same output, so let’s not bother executing it. This is what makes React &lt;em&gt;fast&lt;/em&gt;. It only renders as needed.&lt;/p&gt;

&lt;p&gt;React determines if its props and state are equal the same way JavaScript does — by simply comparing them with the &lt;code&gt;==&lt;/code&gt; operator. React &lt;em&gt;does not&lt;/em&gt; shallow or deep compare objects to determine if they are equal. Shallow comparison is a term used to describe comparing each key-value pair of an object, as opposed to comparing the memory address. Deep comparison is going one step further and, if any of the values in the key-value pair are also objects, comparing those key-value pairs as well, ad nauseum. React does neither: it merely checks if the &lt;em&gt;references&lt;/em&gt; are the same.&lt;/p&gt;

&lt;p&gt;If you were to change a component’s prop from &lt;code&gt;{ x: 1 }&lt;/code&gt; to another object &lt;code&gt;{ x: 1 }&lt;/code&gt;, React will re-render, because those two objects do not reference the same location in memory. If you were to change a component’s prop from &lt;code&gt;object1&lt;/code&gt; (from above) to &lt;code&gt;object3&lt;/code&gt;, React would &lt;em&gt;not&lt;/em&gt; re-render, because those two objects &lt;em&gt;are&lt;/em&gt; the same reference.&lt;/p&gt;

&lt;p&gt;In JavaScript, functions are handled the same way. If React receives an identical function with a different memory address, it will re-render. If React receives the same function reference, it will not.&lt;/p&gt;

&lt;p&gt;This is an unfortunately common scenario I come across during code review:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;SomeComponent&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;PureComponent&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="kd"&gt;get&lt;/span&gt; &lt;span class="nx"&gt;instructions&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;do&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Click the button: &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Do NOT click the button: &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;render&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="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;instructions&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Button&lt;/span&gt; &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;alert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;!&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is a pretty straightforward component. There’s a button, and when it is clicked, it alerts. Instructions tell you whether or not you should click it, which is controlled by the &lt;code&gt;do={true}&lt;/code&gt; or &lt;code&gt;do={false}&lt;/code&gt; prop of &lt;code&gt;SomeComponent&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;What happens here is that every time &lt;code&gt;SomeComponent&lt;/code&gt; is re-rendered (such as &lt;code&gt;do&lt;/code&gt; toggling from &lt;code&gt;true&lt;/code&gt; to &lt;code&gt;false&lt;/code&gt;), &lt;code&gt;Button&lt;/code&gt; is re-rendered too! The &lt;code&gt;onClick&lt;/code&gt; handler, despite being exactly the same, is being &lt;em&gt;created&lt;/em&gt; every &lt;code&gt;render&lt;/code&gt; call. Each render, a new function is created (because it is created in the render function) in memory, a new reference to a new address in memory is passed to &lt;code&gt;&amp;lt;Button /&amp;gt;&lt;/code&gt;, and the &lt;code&gt;Button&lt;/code&gt; component is re-rendered, despite absolutely nothing having changed in its output.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Fix
&lt;/h2&gt;

&lt;p&gt;If your function does not depend on your component (no &lt;code&gt;this&lt;/code&gt; contexts), you can define it outside of the component. All instances of your component will use the same function reference, since the function is identical in all cases.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;createAlertBox&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;alert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;!&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;SomeComponent&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;PureComponent&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="kd"&gt;get&lt;/span&gt; &lt;span class="nx"&gt;instructions&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;do&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Click the button: &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Do NOT click the button: &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;render&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="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;instructions&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Button&lt;/span&gt; &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;createAlertBox&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In contrast to the previous example, &lt;code&gt;createAlertBox&lt;/code&gt; remains the same reference to the same location in memory during every &lt;code&gt;render&lt;/code&gt;. &lt;code&gt;Button&lt;/code&gt; therefore &lt;em&gt;never&lt;/em&gt; has to re-render.&lt;/p&gt;

&lt;p&gt;While &lt;code&gt;Button&lt;/code&gt; is likely a small, quick-to-render component, you may see these inline definitions on large, complex, slow-to-render components, and it can really bog down your React application. It is good practice to simply never define these functions inside the render method.&lt;/p&gt;

&lt;p&gt;If your function &lt;em&gt;does&lt;/em&gt; depend on your component such that you cannot define it outside the component, you can pass a method of your component as the event handler:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;SomeComponent&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;PureComponent&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="nx"&gt;createAlertBox&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;alert&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;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&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="nx"&gt;instructions&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;do&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Click the button: &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Do NOT click the button: &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;render&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="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;instructions&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Button&lt;/span&gt; &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createAlertBox&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this case, each instance of &lt;code&gt;SomeComponent&lt;/code&gt; has a different alert box. The click event listener for &lt;code&gt;Button&lt;/code&gt; needs to be unique to &lt;code&gt;SomeComponent&lt;/code&gt;. By passing the &lt;code&gt;createAlertBox&lt;/code&gt; method, it does not matter if &lt;code&gt;SomeComponent&lt;/code&gt; re-renders. It doesn’t even matter if the &lt;code&gt;message&lt;/code&gt; prop changes! The address in memory of &lt;code&gt;createAlertBox&lt;/code&gt; does not change, meaning &lt;code&gt;Button&lt;/code&gt; does not have to re-render, and you save processing time and improve rendering speed of your application.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;But what if my functions are dynamic?&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Fix (Advanced)
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;&lt;strong&gt;Author’s Note&lt;/strong&gt;&lt;/em&gt;: I wrote the following examples off the top of my head as a way to repeatedly reference the same function in memory. These examples are meant to make comprehension of references easy. While I would recommend reading this section for the purpose of comprehending references, I have included a better implementation at the end that was generously contributed by Chris Ryan via comment. His solution takes into account cache invalidation and React’s built-in memory management.&lt;/p&gt;

&lt;p&gt;There is a very common use case that you have a lot of unique, dynamic event listeners in a single component, such as when mapping an array.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;SomeComponent&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;PureComponent&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;render&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ul&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;list&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;listItem&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
          &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;li&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;listItem&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Button&lt;/span&gt; &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;alert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;listItem&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;          &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/li&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;        &lt;span class="p"&gt;)}&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/ul&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this case, you have a variable number of buttons, making a variable number of event listeners, each with a unique function that you cannot possibly know what is when creating your &lt;code&gt;SomeComponent&lt;/code&gt;. How can you possible solve this conundrum?&lt;/p&gt;

&lt;p&gt;Enter &lt;em&gt;memoization&lt;/em&gt;, or what may be easier to refer to as simply, &lt;em&gt;caching&lt;/em&gt;. For each unique value, create and cache a function; for all future references to that unique value, return the previously cached function.&lt;/p&gt;

&lt;p&gt;This is how I would implement the above example.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;SomeComponent&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;PureComponent&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="c1"&gt;// Each instance of SomeComponent has a cache of click handlers&lt;/span&gt;
  &lt;span class="c1"&gt;// that are unique to it.&lt;/span&gt;
  &lt;span class="nx"&gt;clickHandlers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt;

  &lt;span class="c1"&gt;// Generate and/or return a click handler,&lt;/span&gt;
  &lt;span class="c1"&gt;// given a unique identifier.&lt;/span&gt;
  &lt;span class="nx"&gt;getClickHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="c1"&gt;// If no click handler exists for this unique identifier, create one.&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nb"&gt;Object&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;hasOwnProperty&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;call&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;clickHandlers&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="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;clickHandlers&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;alert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;clickHandlers&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nx"&gt;render&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ul&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;list&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;listItem&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
          &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;li&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;listItem&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Button&lt;/span&gt; &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getClickHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;listItem&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;          &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/li&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;        &lt;span class="p"&gt;)}&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/ul&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each item in the array is passed through the &lt;code&gt;getClickHandler&lt;/code&gt; method. Said method will, the first time it is called with a value, &lt;em&gt;create&lt;/em&gt; a function unique to that value, then return it. All future calls to that method with that value will not create a new function; instead, it will return the reference to the previously created function in memory.&lt;/p&gt;

&lt;p&gt;As a result, re-rendering &lt;code&gt;SomeComponent&lt;/code&gt; will not cause &lt;code&gt;Button&lt;/code&gt; to re-render. Similarly, adding items to the &lt;code&gt;list&lt;/code&gt; prop will create event listeners for each button dynamically.&lt;/p&gt;

&lt;p&gt;You may need to use your own cleverness for generating unique identifiers for each handler when they are determined by more than one variable, but it is not much harder than simply generating a unique &lt;code&gt;key&lt;/code&gt; prop for each JSX object in the mapped result.&lt;/p&gt;

&lt;p&gt;A word of warning for using the &lt;code&gt;index&lt;/code&gt; as the identifier: You may get the wrong result if the list changes order or removes items. When your array changes from &lt;code&gt;[ 'soda', 'pizza' ]&lt;/code&gt; to just &lt;code&gt;[ 'pizza' ]&lt;/code&gt; and you have cached your event listener as &lt;code&gt;listeners[0] = () =&amp;gt; alert('soda')&lt;/code&gt;, you will find that when you users click the now-index-0 button for pizza that it alerts &lt;code&gt;soda&lt;/code&gt;. This is the same reason React advises against using array indices for key props.&lt;/p&gt;

&lt;h2&gt;
  
  
  A Better Implementation
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--lAEQkRuQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/c0snwqrl5r77tcaz4f1j.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--lAEQkRuQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/c0snwqrl5r77tcaz4f1j.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Courtesy of Medium user Chris Ryan.&lt;/em&gt;&lt;/p&gt;

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

&lt;p&gt;If you liked this article, feel free to give it a heart or a unicorn. It’s quick, it’s easy, and it’s free! If you have any questions or relevant great advice, please leave them in the comments below.&lt;/p&gt;

&lt;p&gt;To read more of my columns, you may follow me on &lt;a href="https://www.linkedin.com/in/charles-stover"&gt;LinkedIn&lt;/a&gt;, &lt;a href="https://medium.com/@Charles_Stover"&gt;Medium&lt;/a&gt;, and &lt;a href="https://twitter.com/CharlesStover"&gt;Twitter&lt;/a&gt;, or &lt;a href="https://charlesstover.com/"&gt;check out my portfolio on CharlesStover.com&lt;/a&gt;.&lt;/p&gt;

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