<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Carl Vitullo</title>
    <description>The latest articles on DEV Community by Carl Vitullo (@vcarl).</description>
    <link>https://dev.to/vcarl</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%2F75868%2F57ce0cd3-29e7-4236-ba9c-e5404ec28e79.jpg</url>
      <title>DEV Community: Carl Vitullo</title>
      <link>https://dev.to/vcarl</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/vcarl"/>
    <language>en</language>
    <item>
      <title>Picking Discord role colors</title>
      <dc:creator>Carl Vitullo</dc:creator>
      <pubDate>Mon, 28 Feb 2022 18:18:41 +0000</pubDate>
      <link>https://dev.to/reactiflux/picking-discord-role-colors-9h</link>
      <guid>https://dev.to/reactiflux/picking-discord-role-colors-9h</guid>
      <description>&lt;p&gt;Reactiflux recently added a role menu to allow members to self-identify their experience and attitude at work, which we make visible in the server by a combination of role colors and role icons. While doing so, I had to wrestle with picking effective colors.&lt;/p&gt;

&lt;p&gt;Discord exposes a palette of colors, but the slate of options isn't very rich. We needed to add colors for a total of 8 similar roles, so it was obvious that we'd need to go beyond what Discord makes available.&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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi9u4o9z1xt80occc7k5s.png" 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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi9u4o9z1xt80occc7k5s.png" alt="Discord's role color palette, with 20 colors; ten pairs of bright and faded colors"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We approached this with a couple of goals in mind. We wanted to make it easy to get a rough idea of someone's experience and to give an obvious way to distinguish managers and tech leads. In picking exact colors to use, we were subject to a constraint from Discord as well: role colors must be easy to read for members who use either dark mode or light mode, since we can't select a different color for each.&lt;/p&gt;

&lt;p&gt;For this reason, we chose to use 2 gradients. One to span our 6 individual contributor roles, and another to signify the 2 management track roles. I am in no way a visual designer, but I did my best. I found the tools on &lt;a href="https://colordesigner.io/tools" rel="noopener noreferrer"&gt;colordesigner.io&lt;/a&gt; very helpful for coming up with colors to use, and &lt;a href="https://webaim.org/" rel="noopener noreferrer"&gt;WebAIM&lt;/a&gt; useful to verify contrast ratio.&lt;/p&gt;

&lt;p&gt;I used the &lt;a href="https://colordesigner.io/random-color-generator" rel="noopener noreferrer"&gt;random color generator&lt;/a&gt; to gather a couple of likely candidates for start- and end-colors for the gradient, plugging them into the &lt;a href="https://webaim.org/resources/contrastchecker/" rel="noopener noreferrer"&gt;WebAIM contrast accessibility checker&lt;/a&gt; to verify that the colors had a contrast ratio of at least 3, in both light- and dark-mode.&lt;/p&gt;

&lt;p&gt;Once I had a pair of colors I was happy with, I plugged them into the &lt;a href="https://colordesigner.io/gradient-generator" rel="noopener noreferrer"&gt;gradient generator&lt;/a&gt; to create a set of intermediate colors. It took some trial and error to make sure the entire gradient was sufficiently distinct, and we may iterate on this further.&lt;/p&gt;

&lt;p&gt;I wanted to keep colors from being &lt;em&gt;too&lt;/em&gt; close to each other, while also ensuring they weren't too visually similar to our staff and distinguished member colors.&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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjrqubkma2pk4zla4dj3k.png" 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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjrqubkma2pk4zla4dj3k.png" alt="Our final set of role colors"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We're pretty happy with these! It may be a small detail, but if names are difficult to read then it's that much more difficult to get to know who's in the community, so the work is worth doing.&lt;/p&gt;

&lt;p&gt;Thanks for reading! Reactiflux is the largest chat community of React developers, it's a great place to get help with learning React, level up your skills, or get advice for your career. Check out our &lt;a href="https://www.reactiflux.com/transcripts" rel="noopener noreferrer"&gt;past Q&amp;amp;As&lt;/a&gt; with notable React community members, and &lt;a href="http://discord.gg/reactiflux" rel="noopener noreferrer"&gt;join the conversation yourself!&lt;/a&gt;&lt;/p&gt;

</description>
      <category>community</category>
      <category>a11y</category>
      <category>discord</category>
    </item>
    <item>
      <title>Optimizing a dockerfile</title>
      <dc:creator>Carl Vitullo</dc:creator>
      <pubDate>Wed, 05 Aug 2020 18:09:22 +0000</pubDate>
      <link>https://dev.to/vcarl/optimizing-a-dockerfile-1o2l</link>
      <guid>https://dev.to/vcarl/optimizing-a-dockerfile-1o2l</guid>
      <description>&lt;p&gt;There are 3 major points to consider when optimizing a Docker file:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Build context size&lt;/li&gt;
&lt;li&gt;Cached layers&lt;/li&gt;
&lt;li&gt;Final image size&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Build context size
&lt;/h1&gt;

&lt;p&gt;The build context is the entirety of the disk contents for the folder containing your Dockerfile, except parts ignored by &lt;code&gt;.dockerignore&lt;/code&gt;. This can be massive — on a Javascript application, this means copying over &lt;code&gt;node_modules&lt;/code&gt;, which would be installed as part of the build anyway!&lt;/p&gt;

&lt;p&gt;On a real world example, failing to add &lt;code&gt;node_modules&lt;/code&gt; to my &lt;code&gt;.dockerignore&lt;/code&gt; file yields:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Sending build context to Docker daemon 788.6MB&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;That context transfers at about 30-50MB/s. A significant wait! &lt;em&gt;Just&lt;/em&gt; ignoring &lt;code&gt;node_modules&lt;/code&gt; reduces that to:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Sending build context to Docker daemon 13.75MB&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Which is no wait at all. This alone is an easy win that can save minutes per build if not already configured.&lt;/p&gt;

&lt;h1&gt;
  
  
  Cached layers
&lt;/h1&gt;

&lt;p&gt;Each step in a Dockerfile produces a "layer," which is cached across subsequent runs. The rules for when caches are invalidate are pretty simple:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The line of the Dockerfile is changed&lt;/li&gt;
&lt;li&gt;The resources referenced by &lt;code&gt;ADD&lt;/code&gt; or &lt;code&gt;COPY&lt;/code&gt; change&lt;/li&gt;
&lt;li&gt;Any line above the current one has been invalidated&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This means that we can dramatically reduce the amount of time it takes to re-build a docker image by approaching our Dockerfile with some care.&lt;/p&gt;

&lt;h2&gt;
  
  
  Order commands from least- to most-frequently-changed
&lt;/h2&gt;

&lt;p&gt;We can maximize the amount of layers that remain cached by placing frequently changed resources or instructions later in the file. This is constrained, though, by the process having a necessary order of operations. You can't install your dependencies before copying a manifest, and you can't build your source before installing your dependencies.&lt;/p&gt;

&lt;h2&gt;
  
  
  Un-bundle unrelated instructions
&lt;/h2&gt;

&lt;p&gt;Instead of configuring the OS, installing the dependencies, and building the application in a single step, separate these into discrete steps. Pulling from a real Dockerfile I optimized,&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; ubuntu:16.04&lt;/span&gt;
&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /app/src&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; . /app/src&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;apt-get update &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; apt-get &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; curl git make … &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; apt-get clean
&lt;span class="k"&gt;RUN &lt;/span&gt;yarn &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; yarn build
&lt;span class="c"&gt;# …&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Every time a file anywhere in your project changes, this will start from square 1. &lt;code&gt;COPY . /app/src&lt;/code&gt; is telling it to do exactly that.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; ubuntu:16.04&lt;/span&gt;
&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /app/src&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;apt-get update &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; apt-get &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; curl git make … &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; apt-get clean
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; package.json yarn.lock /app/src/&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;yarn &lt;span class="nb"&gt;install&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; .babelrc webpack.config.js /app/src/&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; src /app/src/src&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;yarn build
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This again can cut minutes per build off the total time spent. Breaking down the steps:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Install OS-level dependencies. These are specified inline, so it will never invalidate unless I edit this line of the Dockerfile.&lt;/li&gt;
&lt;li&gt;Copy my package information and lockfile&lt;/li&gt;
&lt;li&gt;Install dependencies. This step will only invalidate if one of the specified files changes.&lt;/li&gt;
&lt;li&gt;Copy source code and build configuration&lt;/li&gt;
&lt;li&gt;Build the app. This invalidates on every code change.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;COPY&lt;/code&gt; has an awkward experience for this. Files may be copied many at once with the final item in the list being interpreted as the in-image destination folder, but source folders must be specified 1 per &lt;code&gt;COPY&lt;/code&gt; command. Folders are also specified not by the &lt;em&gt;containing&lt;/em&gt; folder, but by the exact folder itself (note &lt;code&gt;COPY src /app/src/src&lt;/code&gt;, not &lt;code&gt;COPY src /app/src&lt;/code&gt;). This leads to some extra layers in complex directory structures, but the advantages of this are huge.&lt;/p&gt;

&lt;p&gt;Consider how long each of these steps takes. I find &lt;code&gt;apt-get&lt;/code&gt; and &lt;code&gt;yarn install&lt;/code&gt; frequently take anywhere from 30 seconds to multiple minutes, &lt;em&gt;each&lt;/em&gt;, and both are completely irrelevant if I'm only making a change to source code.&lt;/p&gt;

&lt;h1&gt;
  
  
  Final image size
&lt;/h1&gt;

&lt;p&gt;The final docker image is, presumably, the artifact that is being produced and passed throughout the rest of the deployment. These may be archived for accountability purposes, uploaded across a network, or otherwise be used in situations where keeping them small is advantageous. Some context first:&lt;/p&gt;

&lt;p&gt;The real-world Dockerfile I've been referencing is a single-page application, and thus is served by nginx. A straightforward way to configure a docker image for this would be to start &lt;code&gt;FROM nginx&lt;/code&gt;, install node, yarn, and all the other tools needed to build it, then copy the resulting files to nginx's content root.&lt;/p&gt;

&lt;p&gt;However this leads to an inefficiency: node, yarn, even my &lt;code&gt;node_modules&lt;/code&gt;, &lt;em&gt;aren't used by nginx&lt;/em&gt;. It's compiled into static html, js, and css. The rest of those tools and resources are now wasted space. Worse, it's a potential security risk! The running server, rather than only having exactly what it needs to execute the production environment, has multiple tools for installing and running external code. (I'll admit to not knowing a precise exploit — security isn't my specialization — but excluding unnecessary tools reduces the attack surface)&lt;/p&gt;

&lt;p&gt;Docker lets us address that with a feature known as "multi-stage builds." We can name intermediate images used to run our build, then extract resources for consumption in a later (more narrowly scoped) image.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; ubuntu:16.04&lt;/span&gt;
&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /app/src&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;apt-get update &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; apt-get &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; curl git make … &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; apt-get clean
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; package.json yarn.lock /app/src/&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;yarn &lt;span class="nb"&gt;install&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; .babelrc webpack.config.js /app/src/&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; src /app/src/src&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;yarn build
&lt;span class="c"&gt;# I’m cheating a bit. These two images aren’t _identical_ because I&lt;/span&gt;
&lt;span class="c"&gt;# don't have a working example of nginx handy. The installation and&lt;/span&gt;
&lt;span class="c"&gt;# execution of nginx is omitted here.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The above dockerfile produces an image that's 2.21GB. I can make this a multi-stage build by naming our "build" image and using a second &lt;code&gt;FROM&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; ubuntu:16.04 as build&lt;/span&gt;
&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /app/src&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;apt-get update &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; apt-get &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; curl git make … &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; apt-get clean
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; package.json yarn.lock /app/src/&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;yarn &lt;span class="nb"&gt;install&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; .babelrc webpack.config.js /app/src/&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; src /app/src/src&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;yarn build
&lt;span class="c"&gt;# Our final image source&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; nginx:1.17&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; --from=build /app/src/dist/ /usr/share/nginx/html/&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; nginx_default.conf /etc/nginx/conf.d/default.conf&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The multi-stage build version produces an image that's 166MB. That's less than one tenth the size! There's surely some additional fat to trim there, as the &lt;a href="https://hub.docker.com/_/nginx?tab=tags"&gt;nginx base images&lt;/a&gt; are about 50MB and my built static files are only about 40MB, but this is quite an improvement over the simplest configuration without spending too much time.&lt;/p&gt;




&lt;p&gt;I've repeated this process on a number applications I've maintained, and it's paid dividends in time saved every time. Time spent waiting for a build is waste time. It breaks me out of my flow, I get distracted and don't notice when it finally finishes, and it makes it so slow to test changes that I don't want to experiment. Optimizations such as these are substantial wins to my productivity.&lt;/p&gt;

</description>
      <category>docker</category>
      <category>programming</category>
      <category>optimizing</category>
    </item>
    <item>
      <title>Securing a large Gatsby site with a CSP</title>
      <dc:creator>Carl Vitullo</dc:creator>
      <pubDate>Tue, 21 Jan 2020 18:55:47 +0000</pubDate>
      <link>https://dev.to/vcarl/securing-a-large-gatsby-site-with-a-csp-12f8</link>
      <guid>https://dev.to/vcarl/securing-a-large-gatsby-site-with-a-csp-12f8</guid>
      <description>&lt;p&gt;(Photo by &lt;a href="https://unsplash.com/photos/P2k3JttAlho" rel="noopener noreferrer"&gt;Piotr Hamryszczak&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;Recently I shipped a large project using some of the hot new tools in the React community—Gatsby and MDX—serving a global audience with about 160 different pages (blog posts, landing pages, and indexes). Because I work in the cryptocurrency space, which has a relatively large population of suspicious actors, I wanted to do everything I could for security. One of the ways I did this was to ensure I had a restrictive Content Security Policy (CSP).&lt;/p&gt;

&lt;p&gt;Content security policies allow you to whitelist where resources can be loaded from, what external connections can be made, and what types of code can be run. It's a way to lock down the wild-west execution environments that are the browsers of the general public by removing certain attack vectors. I learned that CSPs are difficult to get right, but new policies can be rolled out safely.&lt;/p&gt;

&lt;p&gt;CSP rules are granular to the extreme, and the rules for writing them are tricky. Because of how various browsers and common tools work, I discovered that there were many violations I didn't expect, that are difficult to verify, and that there might be new errors at any time. Because CSPs are a whitelist, I had to learn a lot about the details in order to get it working properly.&lt;/p&gt;

&lt;p&gt;It took a lot of trial and error.&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%2Fnx3bgxmamausq108dpcs.png" 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%2Fnx3bgxmamausq108dpcs.png" alt="list of 6 pull requests from September 6th to December 18th"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Limits from Gatsby and MDX
&lt;/h2&gt;

&lt;p&gt;One problem I had very quickly was that Gatsby and MDX, at time of writing, require some large carve-outs in order to operate. There are 2 rules that, left out of the whitelist, close a lot of the methods of XSS attack.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;'unsafe-eval'&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;'unsafe-inline'&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These 2 methods are the most common ways to inject malicious JS onto pages. &lt;code&gt;'unsafe-eval'&lt;/code&gt; prevents strings from being executed as code, and &lt;code&gt;'unsafe-inline'&lt;/code&gt; requires that all scripts be loaded from files over the network. With these two omitted and a list of acceptable domains scripts can come from, this gives you a high degree of confidence that you aren't vulnerable to XSS attacks—your server would have to be compromised before malicious scripts can be executed.&lt;/p&gt;

&lt;p&gt;However, Gatsby itself places many inline styles and scripts on the page, and MDX uses &lt;code&gt;new Function&lt;/code&gt;. Because they make use of this functionality, we have to punch pretty big hole in the security policy. On the one hand, this is pretty great: there are very few problems, it's really really close to letting us be extremely restrictive with our security rules. On the other hand, &lt;em&gt;there are so few problems&lt;/em&gt;: so close, yet so far. I can't lock the policy all the way down.&lt;/p&gt;

&lt;p&gt;Gatsby has &lt;a href="https://github.com/gatsbyjs/gatsby/issues/10890" rel="noopener noreferrer"&gt;an umbrella issue&lt;/a&gt; for these problems, and there's &lt;a href="https://github.com/ChristopherBiscardi/gatsby-mdx/issues/303#issuecomment-469095503" rel="noopener noreferrer"&gt;a workaround for MDX&lt;/a&gt; (with some restrictions on how you can write your code). There's also &lt;a href="https://github.com/bejamas/gatsby-plugin-csp" rel="noopener noreferrer"&gt;&lt;code&gt;gatsby-plugin-csp&lt;/code&gt;&lt;/a&gt;, which will determine hashes for inlined scripts so they can be whitelisted without &lt;code&gt;unsafe-inline&lt;/code&gt;, but it outputs to a &lt;code&gt;&amp;lt;meta&amp;gt;&lt;/code&gt; tag thus disallowing &lt;code&gt;report-uri&lt;/code&gt;. Ultimately these options didn't work for my codebase.&lt;/p&gt;

&lt;h2&gt;
  
  
  Launching the CSP
&lt;/h2&gt;

&lt;p&gt;After getting a CSP that allowed all our images, any iframes, data sources, embedded media, and form submission targets, I added it in report-only mode and set it loose. This is what makes it so easy to roll out a new CSP: you can put it in place where it will emit errors, but not block content. This lets you spot problems before they surface for your visitors and fix errors before they see them.&lt;/p&gt;

&lt;p&gt;In rolled the browser errors. Some are frequent enough to make me think it's every user of a certain device or browser, teaching me something about how varied the web is. One error that seems obvious in hindsight is translation services. I found Google Translate specifically difficult to test, though. The website allows you to browse via an iframe, which runs into completely different CSP rules as the in-Chrome "do you want to translate this page?" prompt, and it took a trick to make that prompt appear.&lt;/p&gt;

&lt;h2&gt;
  
  
  Quickly finding mistakes
&lt;/h2&gt;

&lt;p&gt;Very fortuitously, one of my good friends published a CSP evaluation tool, &lt;a href="https://csper.io/#/evaluator" rel="noopener noreferrer"&gt;csper.io&lt;/a&gt;, which helped me catch a number of silly mistakes that accidentally weakened my policy. CSPs have an fiddly syntax, and because they only warn when the rule is violated, broken rules can be invisible.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;&lt;span class="gd"&gt;-base-uri none;
&lt;/span&gt;&lt;span class="gi"&gt;+base-uri 'none';
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In CSPs, values without strings are interpreted as URLs. Here, &lt;code&gt;none&lt;/code&gt; is actually being interpreted as &lt;code&gt;https://none&lt;/code&gt;. This isn't a &lt;em&gt;large&lt;/em&gt; problem, because that's not a domain that can be registered and thus not a significant vector, but it's annoying to accidentally leave something subtly broken.&lt;/p&gt;

&lt;h2&gt;
  
  
  The final policy
&lt;/h2&gt;

&lt;p&gt;The final CSP is quite long, much longer than I expected going into it. (I've anonymized this to remove specific servers, replacing them with generic addresses)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;block-all-mixed-content;
base-uri 'none';
default-src 'self';
object-src 'none';
frame-ancestors 'self';

form-action https://company-name.us9.list-manage.com;

img-src data: https: android-webview-video-poster: android-webview:;

font-src data: 'self' https://cdn.embedly.com https://fonts.gstatic.com;

style-src 'unsafe-inline' 'self' https://translate.googleapis.com https://cdn.embedly.com;

frame-src https://runkit.com https://third-party-iframe.example.com https://www.youtube.com https://cdn.embedly.com;

connect-src 'self' https://company-api.example.com https://sentry.io https://third-party-api.example.com https://api-cdn.embed.ly https://translate.googleapis.com https://www.google-analytics.com;

script-src 'self' 'unsafe-eval' 'unsafe-inline' 'data' https://embed.runkit.com https://www.google-analytics.com https://company-name.us9.list-manage.com https://translate.googleapis.com https://translate.google.com https://api.microsofttranslator.com cdn.embedly.com;

report-uri https://sentry.io/api/id/security/?sentry_key=key;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  In summary
&lt;/h2&gt;

&lt;p&gt;Because this is a whitelist, I know that I'll have to keep an eye on the violations to see if useful services become blocked in the future. If a translation service starts using a new domain, it won't work until I add it to the whitelist. There are enough real violations to make this a large set to sort through, making that a bit of a challenge. &lt;/p&gt;

&lt;p&gt;Csper helped me tighten up my rules by giving me prioritized suggestions, which I found reasonable and easy to change. They were also descriptive enough that I learned a lot about the possible attack vectors that websites face. For a fee, it can also be used for long-term monitoring, which could prove more useful than Sentry's reports due to the specialization.&lt;/p&gt;

&lt;p&gt;Overall, I felt adding a CSP was worth the effort invested in adding it, though the process was slower moving than I'd hoped. Because errors frequently came from unusual combinations of browsers, extensions, and third-party tools, I needed to gather several days worth of reports before I felt confident after making any changes to the policy. If I had started from &lt;a href="https://csper.io/#/evaluator" rel="noopener noreferrer"&gt;csper.io&lt;/a&gt;, I think I would have saved myself a lot of time when I was learning how CSPs work.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>react</category>
      <category>security</category>
      <category>gatsby</category>
    </item>
    <item>
      <title>What was your worst new job experience?</title>
      <dc:creator>Carl Vitullo</dc:creator>
      <pubDate>Fri, 09 Aug 2019 15:46:00 +0000</pubDate>
      <link>https://dev.to/techworkersco/what-was-your-worst-new-job-experience-4lgb</link>
      <guid>https://dev.to/techworkersco/what-was-your-worst-new-job-experience-4lgb</guid>
      <description>&lt;p&gt;Sometimes you start a new job and quickly realize it's not a good fit. What's your worst new job story?&lt;/p&gt;

</description>
      <category>career</category>
      <category>discuss</category>
    </item>
    <item>
      <title>Why do you love your job?</title>
      <dc:creator>Carl Vitullo</dc:creator>
      <pubDate>Fri, 02 Aug 2019 19:05:17 +0000</pubDate>
      <link>https://dev.to/techworkersco/why-do-you-love-your-job-1cn8</link>
      <guid>https://dev.to/techworkersco/why-do-you-love-your-job-1cn8</guid>
      <description>&lt;p&gt;Jobs aren't all frustration and misery. What does you job do for you that makes you happy to stay where you are? The benefits, a great perk, your coworkers, the projects?&lt;/p&gt;

</description>
      <category>discuss</category>
      <category>career</category>
    </item>
    <item>
      <title>What made you quit your job?</title>
      <dc:creator>Carl Vitullo</dc:creator>
      <pubDate>Fri, 26 Jul 2019 17:36:46 +0000</pubDate>
      <link>https://dev.to/techworkersco/what-made-you-quit-your-job-4bch</link>
      <guid>https://dev.to/techworkersco/what-made-you-quit-your-job-4bch</guid>
      <description>&lt;p&gt;Our industry has a reputation for short employment tenures. What circumstances tipped you over the edge into quitting your job?&lt;/p&gt;

</description>
      <category>discuss</category>
      <category>career</category>
    </item>
    <item>
      <title>How a walkout happens in tech</title>
      <dc:creator>Carl Vitullo</dc:creator>
      <pubDate>Tue, 09 Jul 2019 16:44:39 +0000</pubDate>
      <link>https://dev.to/vcarl/how-a-walkout-happens-in-tech-26g2</link>
      <guid>https://dev.to/vcarl/how-a-walkout-happens-in-tech-26g2</guid>
      <description>&lt;p&gt;At 1:30pm on Wednesday, June 26th, hundreds of Wayfair employees walked out of the office after failing to reach an agreement with Wayfair's executives about furnishing an ICE detention center.&lt;/p&gt;

&lt;p&gt;What I wanted to know is, how does a walkout happen? What is the sequence events that begins with somebody sharing an opinion and ends with hundreds of people risking their livelihood?&lt;/p&gt;

&lt;p&gt;Largely pieced together from &lt;a href="https://www.vice.com/en_us/article/a3x84z/wayfair-is-profiting-from-immigration-detention-so-im-walking-out"&gt;an interview done with Vice&lt;/a&gt;, I've put together a rough timeline. I'm filling in gaps to the best of my ability, but I haven't been able to make direct contact with anyone involved in organizing the walkout.&lt;/p&gt;

&lt;h1&gt;
  
  
  The sequence of events
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Early 2019
&lt;/h2&gt;

&lt;p&gt;A worker at Wayfair sees a sale to BCFS, a contractor for ICE with a reputation for sub-standard facilities, and an unknown number of people raise concerns to management. No action was taken.&lt;/p&gt;

&lt;h2&gt;
  
  
  June 19th
&lt;/h2&gt;

&lt;p&gt;A second sale to BCFS is spotted and disseminated, reportedly to a group of around 24 coworkers throughout the company. This group meets the next day to draft a letter to management with 2 specific requests.&lt;/p&gt;

&lt;h2&gt;
  
  
  June 21st
&lt;/h2&gt;

&lt;p&gt;A digital copy of the letter is circulated internally, with a link to an external form used to digitally sign it. After about 4 hours, the organizers deliver it to management with 547 signatures.&lt;/p&gt;

&lt;h2&gt;
  
  
  June 24th
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://twitter.com/FizFashizzle/status/1143530739541139457"&gt;Management responds, negatively&lt;/a&gt;. They "appreciate your passion and commitment," and are "proud to have such an engaged team," but decline to actually do anything in response.&lt;/p&gt;

&lt;h2&gt;
  
  
  June 25th
&lt;/h2&gt;

&lt;p&gt;Tuesday morning, the management response &lt;a href="https://twitter.com/FizFashizzle/status/1143530739541139457"&gt;was tweeted&lt;/a&gt;. Later that day, it became a national issue with &lt;a href="https://twitter.com/AOC/status/1143590995122171905"&gt;AOC&lt;/a&gt; and &lt;a href="https://twitter.com/BernieSanders/status/1143610481854300161"&gt;Bernie Sanders&lt;/a&gt; tweeting in support of it. After news of the walkout breaks, management shifts their position to &lt;a href="https://www.cnn.com/2019/06/26/business/wayfair-donation-migrant-facility/index.html"&gt;donating $100k&lt;/a&gt; to the Red Cross—not to &lt;a href="https://www.raicestexas.org"&gt;RAICES&lt;/a&gt;, an immigrant rights group, as proposed by the organizers.&lt;/p&gt;

&lt;h2&gt;
  
  
  June 26th
&lt;/h2&gt;

&lt;p&gt;Workers walk out.&lt;/p&gt;


&lt;blockquote class="ltag__twitter-tweet"&gt;
      &lt;div class="ltag__twitter-tweet__media"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--pxFSxX3q--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://pbs.twimg.com/media/D-BaSDpU8AE5vnT.jpg" alt="unknown tweet media content"&gt;
      &lt;/div&gt;

  &lt;div class="ltag__twitter-tweet__main"&gt;
    &lt;div class="ltag__twitter-tweet__header"&gt;
      &lt;img class="ltag__twitter-tweet__profile-image" src="https://res.cloudinary.com/practicaldev/image/fetch/s--xYMYIzS8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://pbs.twimg.com/profile_images/1143631908431003648/uE7_zgoa_normal.jpg" alt="wayfairwalkout profile image"&gt;
      &lt;div class="ltag__twitter-tweet__full-name"&gt;
        wayfairwalkout
      &lt;/div&gt;
      &lt;div class="ltag__twitter-tweet__username"&gt;
        @wayfairwalkout
      &lt;/div&gt;
      &lt;div class="ltag__twitter-tweet__twitter-logo"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--P4t6ys1m--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://practicaldev-herokuapp-com.freetls.fastly.net/assets/twitter-f95605061196010f91e64806688390eb1a4dbc9e913682e043eb8b1e06ca484f.svg" alt="twitter logo"&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="ltag__twitter-tweet__body"&gt;
      It was awesome to see the turnout today. Thank you to everyone who showed up to the &lt;a href="https://twitter.com/hashtag/WayfairWalkout"&gt;#WayfairWalkout&lt;/a&gt; 
    &lt;/div&gt;
    &lt;div class="ltag__twitter-tweet__date"&gt;
      22:44 PM - 26 Jun 2019
    &lt;/div&gt;


    &lt;div class="ltag__twitter-tweet__actions"&gt;
      &lt;a href="https://twitter.com/intent/tweet?in_reply_to=1144013585586126848" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="/assets/twitter-reply-action.svg" alt="Twitter reply action"&gt;
      &lt;/a&gt;
      &lt;a href="https://twitter.com/intent/retweet?tweet_id=1144013585586126848" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="/assets/twitter-retweet-action.svg" alt="Twitter retweet action"&gt;
      &lt;/a&gt;
      410
      &lt;a href="https://twitter.com/intent/like?tweet_id=1144013585586126848" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="/assets/twitter-like-action.svg" alt="Twitter like action"&gt;
      &lt;/a&gt;
      2725
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/blockquote&gt;


&lt;p&gt;It's hard to get a count, and it's hard to know how many in the crowd are Wayfair employeers vs friends of the walkout showing solidarity, but this looks like a big turnout to me. Direct actions like this are risky, so Tech Workers Coalition &lt;a href="https://mobile.twitter.com/techworkersco/status/1144039406292127744"&gt;set up a hotline&lt;/a&gt; in case any workers face retaliation.&lt;/p&gt;

&lt;h1&gt;
  
  
  Analyzing it
&lt;/h1&gt;

&lt;p&gt;I'd bet that the genesis of the walkout could be traced back to shortly after the first complaints were dismissed. All the ingredients were there; like-minded folks throughout the company came together with a shared complaint, and management took no action in response. Organized actions begin with a few people talking, and if they didn't already know each other, that's likely when they started collaborating.&lt;/p&gt;

&lt;p&gt;Two questions I have for the organizers about the early stages:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Did you already know a group of coworkers who were opposed to this type of sale? How did you reach out to them about this sale?&lt;/li&gt;
&lt;li&gt;How did you know to look for BCFS?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://twitter.com/sun_daiz/status/1143548274240102401"&gt;The letter&lt;/a&gt; to management is so well composed and thoroughly cited that I have to assume it wasn't written from scratch in 1 day. That, more than anything, makes me think that significant effort was put into planning this walkout in the months between sales to BCFS.&lt;/p&gt;

&lt;p&gt;I feel this letter, as the primary contact between a large group of employees and the company's owners, is one of the most important tools. Later on, I break down the letter and offer my analysis of what they've written. I have a tiny bit of experience here—I helped draft &lt;a href="https://github.com/palantir/blueprint/pull/3535/files?short_path=2f4c358#diff-2f4c3585a94a03c11192c3ae940fcb70"&gt;a letter&lt;/a&gt; attempting to &lt;a href="https://www.theguardian.com/us-news/2019/may/13/tech-workers-palantir-immigration-protest-github"&gt;convince Palantir employees to resist ICE&lt;/a&gt; contract renewal from the inside.&lt;/p&gt;

&lt;p&gt;Almost certainly, the meeting on the 20th was where the walkout was concretely decided upon—a contingency in case an agreement couldn't be reached.&lt;/p&gt;

&lt;p&gt;Three questions I have about their first meeting and writing the letter:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How much planning happened in advance of this meeting?&lt;/li&gt;
&lt;li&gt;What were your guiding principles when writing the letter?&lt;/li&gt;
&lt;li&gt;When in the course of this did you plan the walkout?&lt;/li&gt;
&lt;/ul&gt;




&lt;h1&gt;
  
  
  Tearing apart the letter to management
&lt;/h1&gt;

&lt;p&gt;The full letter these workers submitted to management was &lt;a href="https://twitter.com/sun_daiz/status/1143548274240102401"&gt;posted on Twitter&lt;/a&gt;. This is a great artifact of a successful action. I'd like to break down how it was written, and why, to learn how to write something similar.&lt;/p&gt;

&lt;p&gt;The most important thing when writing, I've found, is to have a clear idea of who I'm speaking to and what I want them to take away from it. The audience here is obvious: management, specific individuals that the authors probably know, at least by reputation. What should they take away from it? From their previous behavior, it's clear that they don't agree that it's wrong to accept money from BCFS. It's hard to change somebody's mind, especially when they have a financial interest in staying the course. Let's look at each paragraph and guess at how Wayfair's leadership might receive it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Paragraph 1
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--hrLnVIaz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.vcarl.com/images/wayfair-1.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--hrLnVIaz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.vcarl.com/images/wayfair-1.jpg" alt="Paragraph 1"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The opening paragraph is straight and to the point without using (excessively) inflammatory language. It clearly communicates the emotions involved without letting them bleed into the words used. It offers citations for its strongest claims—some might dispute the use of the term "atrocities," and it preempts them by offering examples. This introduction sets the stage for the rest of the letter, explaining for whom it speaks and what issues they're speaking about.&lt;/p&gt;

&lt;p&gt;However, I think some parts of this might be poorly received by a leader within Wayfair. If I were asked to edit this, I might have changed it to,&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;We, the &lt;strong&gt;547&lt;/strong&gt; undersigned, are writing to you from a place of concern and anger about &lt;strong&gt;Wayfair's role in&lt;/strong&gt; the atrocities being committed at our Southern border. The United States government and its contractors are responsible for the detention and mistreatment of hundreds of thousands of migrants seeking asylum in our country&lt;del&gt; -- we want that to end&lt;/del&gt;. We &lt;del&gt;also&lt;/del&gt; want to be sure that Wayfair has no part in enabling, supporting, or profiting from this practice. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Immediately sharing the number of people that have signed the letter helps sell the the weight rest of its contents, assuming it's a high number—in this case, 547 seems high to me. I'd also emphasize the focus on what Wayfair controls—Wayfair has no leverage to end the atrocities, so it distracts from the main request.&lt;/p&gt;

&lt;h2&gt;
  
  
  Paragraph 2
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--4T3XQRPA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.vcarl.com/images/wayfair-2.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--4T3XQRPA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.vcarl.com/images/wayfair-2.jpg" alt="Paragraph 2"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Emphasizing that this isn't the first occurrence ups the ante significantly. The footnote explains that BCFS's first purchase of Wayfair's products were used at a camp that was later found to be substandard. This increases the veracity of the claims: BCFS isn't assumed to be a bad actor by association with detention, there is evidence of their own bad behavior.&lt;/p&gt;

&lt;p&gt;However, I feel the lede has been buried in a footnote. Comparatively, the UN statement on child rights violations feels abstract; a statement by an international governing body condemning child detention is much less immediate than information that their customer has previously put children at risk.&lt;/p&gt;

&lt;h2&gt;
  
  
  Paragraph 3
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--GZg-kNIf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.vcarl.com/images/wayfair-3.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--GZg-kNIf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.vcarl.com/images/wayfair-3.jpg" alt="Paragraph 3"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Solidly bringing it back to Wayfair's own ideals, a VP of B2B sales is quoted directly. Using an executive's own words in support of their cause is powerful—Wayfair can't dispute the message, it's from one of their own. This paragraph is short, punchy, and neatly measures their complaints against the business' aspirations.&lt;/p&gt;

&lt;h2&gt;
  
  
  Paragraph 4
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--GYqBNDxM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.vcarl.com/images/wayfair-4.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--GYqBNDxM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.vcarl.com/images/wayfair-4.jpg" alt="Paragraph 4"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Finally, the asks. They're limited in scope and accomplishable. It's a combination of rectifying a wrong and making an organizational change to prevent the wrong from reoccurring. They're directly related to a recent event within the company, and were presented in a timely manner.&lt;/p&gt;




&lt;h2&gt;
  
  
  Management's response
&lt;/h2&gt;

&lt;p&gt;This letter is fantastically written, and the asks are reasonable. And yet:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;We believe all of our stakeholders, employees, customers, investors, and suppliers included, are best served by our commitment to fulfill all orders. &lt;a href="https://twitter.com/FizFashizzle/status/1143530739541139457"&gt;Management's response&lt;/a&gt;, delivered the next day, is a flat no. (&lt;a href="///images/wayfair-response.jpg"&gt;Mirror&lt;/a&gt;, in case the tweet is removed)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Thus the walkout. It offers a good reminder: It's not enough to complain if your company is doing something that you and your colleagues feel is wrong. If complaints aren't met with change, it must escalate to action.&lt;/p&gt;

</description>
      <category>career</category>
      <category>organizing</category>
    </item>
    <item>
      <title>The future of Bitcoin and Ethereum</title>
      <dc:creator>Carl Vitullo</dc:creator>
      <pubDate>Sat, 09 Feb 2019 02:35:55 +0000</pubDate>
      <link>https://dev.to/vcarl/the-future-of-bitcoin-and-ethereum-4gkj</link>
      <guid>https://dev.to/vcarl/the-future-of-bitcoin-and-ethereum-4gkj</guid>
      <description>&lt;p&gt;I’ve loosely followed cryptocurrency for almost a decade. In 2011, I briefly mined Bitcoin (and Litecoin, when it became clear that GPU mining BTC was unlikely to net me much of a reward). Bitcoin’s proof-of-work algorithm to create a trustless ledger was a true innovation in decentralized systems, and Ethereum’s expansion of it into a general compute platform was another giant leap. But looking at the state of the world right now, neither seems poised for the level of success that is evangelized.&lt;/p&gt;

&lt;p&gt;I am bullish on cryptocurrency in general. Our existing monetary system already operates on a digital ledger, and reducing institutional trust is a good thing. Moving money and tracking ownership is too important to leave in the custody of private institutions that have a long history of looking out for number one. Yet both Bitcoin and Ethereum strike me as being an imperfect fit for mainstream financial products. Some problems I see:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Block discovery is too long to be used for payments. &lt;/li&gt;
&lt;li&gt;High volatility limits use as a method of payment. &lt;/li&gt;
&lt;li&gt;Smart contracts are too unreliable for institutions.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These problems are substantial hurdles that Bitcoin and Ethereum will have to face in the coming years.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;I'm going to assume the reader is familiar with how cryptocurrencies operate, at least at a high level. The YouTube channel &lt;a href="https://www.youtube.com/watch?v=bBC-nXj3Ng4"&gt;3Brown1Blue&lt;/a&gt; has a fantastic explanation of the proof-of-work algorithm, and &lt;a href="https://support.coinbase.com/customer/en/portal/topics/1070101-digital-currency/articles"&gt;Coinbase&lt;/a&gt; has decent simple explanations of common cryptocurrencies and related topics.&lt;/em&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Long block discovery
&lt;/h1&gt;

&lt;p&gt;Bitcoin has notoriously long transaction times, taking up to an hour to fully settle on the network. This isn’t an inherent property of Bitcoin. The core developers have chosen to keep block discovery times averaging about 10 minutes and the amount of data per block low, which limit transaction latency and throughput respectively. Because proof-of-work requires several blocks to be found before a transaction settles, the transaction time is a multiple of Bitcoin’s 10-minute block time. Ethereum’s block time is 15 seconds, for a point of comparison.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The transaction time is a multiple of Bitcoin’s 10-minute block time.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This puts Bitcoin transactions at a speed somewhere between an ACH transfer and a credit card. It’s not fast enough to use at the corner store, but it could work for some sort of payments app; a slow Venmo or Square Cash. Ethereum is much better, but its 15 second block time means transactions usually settle in about 3 minutes. This is suitable (if a little slow) for a payments app, but far too long a wait if you’re checking out with a line.&lt;/p&gt;

&lt;p&gt;There are serious efforts to address this. The &lt;a href="http://lightning.network/"&gt;lightning network&lt;/a&gt; is way for two parties to confidently settle numerous transactions off-chain, only bringing it back onto the chain once they've completed their transactions with each other. With enough individuals maintaining these payment channels, a payment could occur between 2 parties without a direct connection by making multiple "hops" where connections exist. The lightning network is currently operating in a limited capacity, and in the future it could extend to cross-chain payments—acting as a compatibility layer between different protocols. &lt;/p&gt;

&lt;h1&gt;
  
  
  Price volatility and new currencies
&lt;/h1&gt;

&lt;p&gt;Volatility causes fewer direct problems than slow transactions, but it makes it difficult to use as a means of transfer. The long transaction times and volatility exacerbate &lt;a href="https://www.investopedia.com/terms/m/marketrisk.asp"&gt;market risk&lt;/a&gt;, the potential that the currency’s value will decrease by the time the recipient is able to sell what they’ve been given. &lt;a href="https://steamcommunity.com/games/593110/announcements/detail/1464096684955433613"&gt;Steam stopped accepting it in late 2017&lt;/a&gt; for exactly this reason.&lt;/p&gt;

&lt;p&gt;Those paying suffer the same market risk in the other direction. The currency might increase in value, encouraging you to hold onto it rather than spend it. If you were paid with Bitcoin last week, you don’t know how much purchasing power it will hold next week. The macro-scale impact of this volatility is visible in the decline of BTC as a payment option and the rise of the “hodlers.”&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If you were paid with Bitcoin last week, you don’t know how much &amp;gt; purchasing power it will hold next week.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This price volatility has some organizations attempting to hybridize fiat currency with cryptocurrency, leading to a rise in “stablecoins”—digital assets anchored to real-world currencies. A notable example of this is Tether, USDT, a representation of the US dollar on the blockchain. These introduce new risks: Tether has had major delays fulfilling withdrawal requests, and is accused of &lt;a href="https://medium.com/@bitfinexed/bitfinex-and-tether-is-unauditable-why-they-will-never-do-a-real-audit-3324e002b185"&gt;not having adequate balances to fulfill its obligations&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The driving force behind the volatility is that cryptocurrencies are treated as stock in the projects that issue them. Cryptocurrency enthusiasts behave like speculators, hoping to buy low and sell high. The price fluctuates significantly based on project news and the cryptocurrency market overall, which has the Securities and Exchange Commission keeping a close eye on the space.&lt;/p&gt;

&lt;h1&gt;
  
  
  Smart contracts aren’t reliable
&lt;/h1&gt;

&lt;p&gt;Bitcoin doesn’t have a concept of “smart contracts” in its protocol, but it’s a core innovation of Ethereum. Ethereum provides guarantees about execution and integrity of data for smart contracts, but they’re still arbitrary computer programs. While this opens up the fascinating world of decentralized apps, it’s not ideal for applications that require a high level of security. It's bad if CryptoKitties has a bug allowing attackers to steal your unique cat, but it’s life altering if attackers steal all of your money.&lt;/p&gt;

&lt;p&gt;Many of the potential applications of smart contracts demand such high security. &lt;a href="https://twitter.com/vitalikbuterin/status/1072158957999771648?lang=en"&gt;Vitalik has tweeted&lt;/a&gt; about non-financial applications, but verifying college degrees would be similarly catastrophic if something were to go wrong.&lt;/p&gt;

&lt;p&gt;As arbitrary computer programs, Ethereum’s smart contracts provide no guarantees that they will execute correctly. This relates to the idea of “correctness” in computer science: How do you prove, without executing the code, that it will do what you expect? In the world of Ethereum, your only option is a careful review of the code, with some limited assistance from auditing software. This is hardly compelling to major institutions that already operate systems with a high level of confidence.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Ethereum’s smart contracts provide no guarantees that they will &amp;gt; execute correctly.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Major bugs in high-profile projects shows how difficult smart contracts are to get right. Even Coinbase, arguably the most trusted name in cryptocurrency, had a bug &lt;a href="https://thenextweb.com/hardfork/2018/03/21/coinbase-smart-contract-bug-allowed-crediting/"&gt;allowing users to credit their account with unlimited Ethereum&lt;/a&gt;. The most infamous is &lt;a href="https://medium.com/swlh/the-story-of-the-dao-its-history-and-consequences-71e6a8a551ee"&gt;the DAO hack&lt;/a&gt;, which was reverted by a hard fork of the Ethereum chain and lead to the Ethereum/Ethereum Classic split. Parity, a wallet written as a smart contract, &lt;a href="https://www.parity.io/the-multi-sig-hack-a-postmortem/#wasthewalletnotaudited"&gt;is described&lt;/a&gt; as having been “audited by the Ethereum Foundation’s DEV team, Parity and others from the community.” Yet it suffered multiple &lt;a href="https://blog.zeppelin.solutions/on-the-parity-wallet-multisig-hack-405a8c12e8f7"&gt;hacks&lt;/a&gt; and &lt;a href="https://github.com/paritytech/parity-ethereum/issues/6995"&gt;bugs&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Because the Ethereum protocol acts as a runtime for smart contracts, even smart contracts that are well implemented are vulnerable to bugs introduced at a protocol level. A recent protocol upgrade, codenamed Constantinople, was delayed after ChainSecurity discovered it would make previously secure smart contracts &lt;a href="https://blog.ethereum.org/2019/01/15/security-alert-ethereum-constantinople-postponement/"&gt;vulnerable to a “reentrancy attack.”&lt;/a&gt; It’s difficult for me to imagine any such institution making a significant investment into a technology that has a consistent track record of security vulnerabilities and hacks.&lt;/p&gt;




&lt;h1&gt;
  
  
  What does this mean for Bitcoin and Ethereum?
&lt;/h1&gt;

&lt;p&gt;Bitcoin’s flaws are not inherent to the protocol, but politics within its development means that it’s unlikely to change. The entrenched community of miners and supporters may make it impossible to include the large changes needed to make it competitive with more modern blockchain technologies.&lt;/p&gt;

&lt;p&gt;Ethereum’s problems are perhaps more fundamental and might be harder to fix. The premise of the technology is that anyone can write code for a global computer, but I struggle to see use cases that aren’t better served by a centralized system. This has borne out in the projects that have been built on Ethereum; the most widely successful smart contracts (excluding ERC20 tokens) are for trading or games. These products are popular with cryptocurrency enthusiasts, but only serve those who are already actively interested in the space.&lt;/p&gt;

&lt;p&gt;Cryptocurrencies have become self-serving, insular communities. Far from what was proselytized—a global equalizer, a means of transfer unrestricted by any one party—they have become just another type of investment for those with wealth to invest in. Neither Bitcoin or Ethereum have demonstrated that they’re well-suited to solve any of the world’s problems. I don’t believe that either of them fill a real need in the world in their current state, and their ecosystems and communities work now only to fill their own needs. &lt;/p&gt;

</description>
      <category>cryptocurrency</category>
      <category>future</category>
    </item>
    <item>
      <title>Symptoms of a dysfunctional team</title>
      <dc:creator>Carl Vitullo</dc:creator>
      <pubDate>Mon, 21 Jan 2019 16:36:58 +0000</pubDate>
      <link>https://dev.to/vcarl/symptoms-of-a-dysfunctional-team-1c0</link>
      <guid>https://dev.to/vcarl/symptoms-of-a-dysfunctional-team-1c0</guid>
      <description>&lt;p&gt;(image credit: &lt;a href="https://unsplash.com/photos/w9YHKTK-wLo" rel="noopener noreferrer"&gt;rawpixel&lt;/a&gt; on unsplash)&lt;/p&gt;

&lt;p&gt;I've had a lot of jobs (8 since 2012), which means I've worked with a lot of teams. One of the main reasons I changed jobs so frequently for a couple years is that many of the teams I joined felt very dysfunctional—it was difficult to get work done and there wasn't a clear sense of purpose.&lt;/p&gt;

&lt;p&gt;Hopefully, my cheat sheet of &lt;a href="https://gist.github.com/vcarl/14275c72baf976ff1665392e14225dcc" rel="noopener noreferrer"&gt;questions for your interviewer&lt;/a&gt; will help you identify dysfunctional environments during the interview process, but when you're early in your career it's hard to tell whether your team is functioning as it should. There are some symptoms that I've found to indicate that a team has major cultural or technical issues that cause it to be dysfunctional.&lt;/p&gt;

&lt;h1&gt;
  
  
  Overtime assumed
&lt;/h1&gt;

&lt;p&gt;The biggest indicator is when it becomes assumed that you'll regularly work beyond the 40 hours a week for which you're paid. Software development positions are notorious for a culture of overwork and burnout. In most professions, the federal Fair Labor Standards Act requires that overtime is paid at 1.5x your hourly rate, with salaried positions considered "exempt." However, the FLSA &lt;a href="https://www.dol.gov/whd/overtime/fs17e_computer.htm" rel="noopener noreferrer"&gt;specifically exempts all computer professionals from overtime pay&lt;/a&gt;, which laid the groundwork for burnout culture to flourish.&lt;/p&gt;

&lt;p&gt;Overtime means that too much work has been planned for too little time. It's generally understood that overtime has a detrimental effect on productivity. A &lt;a href="https://kcuc.org/wp-content/uploads/2013/11/R402A-Extended-Overtime-on-Construction-Projects.pdf" rel="noopener noreferrer"&gt;synthesis of studies from 2004&lt;/a&gt; evaluating productivity in construction projects has clear figures showing the drop in productivity. There are potential benefits to brief "crunches" of 1-2 weeks of 50 hours of work, but beyond that and the drop in productivity outweighs the additional time worked. That's right: studies show that those working 60+ hour weeks accomplish &lt;em&gt;less&lt;/em&gt; than people working 40.&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%2Fb8kw271ois94ydbjlotf.PNG" 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%2Fb8kw271ois94ydbjlotf.PNG" alt="A scatterplot titled "&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Long feedback cycles
&lt;/h1&gt;

&lt;p&gt;One of the biggest drains of productivity is long feedback cycles. When you change a line of code, how long do you have to wait before you can tell if it worked? With modern tools and languages, cycle time should be measured in tens of seconds, if not less, but what you can expect depends on the domain you work in. Reducing small amounts of wasted time in repetitive tasks adds up, especially when they're done frequently. As always, there's a &lt;a href="https://xkcd.com/1205/" rel="noopener noreferrer"&gt;relevant XKCD&lt;/a&gt;:&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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs0lkfya38rrykgj3qmos.png" 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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs0lkfya38rrykgj3qmos.png" alt="A chart titled "&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If it takes multiple minutes to run a development build, consider how many hours your team spends collectively sitting idle. Outside of build times, some of this optimization is up to you as a developer; is there a way for you to short-circuit directly to the code path you're testing? If it takes you 10 seconds to click through UI or input data, that can quickly add up to hours of burned time over weeks of development. Modifying the surrounding code to remove these manual steps can have a significant impact on how quickly you can work.&lt;/p&gt;

&lt;p&gt;A major contributing factor to long build times is how familiar your team is with the tools they use.&lt;/p&gt;

&lt;h1&gt;
  
  
  Lack of expertise with tools used
&lt;/h1&gt;

&lt;p&gt;If a tool has been misconfigured, is being used without optimization, or solves a different problem than what your team has, the length of the feedback cycle is often the most visible indicator that something is wrong. Build times (both in development and when deploying to production) and the time needed to configure a local development environment are excellent proxies for your team's overall level of expertise with their tools as well.&lt;/p&gt;

&lt;p&gt;One of the most common reasons behind a team lacking expertise with their tools is when they've followed trends, rather than addressed the problems they encounter. Frontend and Javascript developers are often criticized for this behavior, but I've seen it in backend and ops as well—big data, serverless, AI, Docker, microservices. These are useful, innovative new tools, but using cutting-edge tools that you don't understand is worse than simpler infrastructure you're more familiar with. &lt;/p&gt;

&lt;p&gt;It's hard to judge whether the team understands a tool if you yourself don't, but you can clarify what problems a tool is meant to solve by talking with others. Within your team, there should be a clear answer for why the tool is used and why it was picked over alternatives. Talking with others outside the team, like at a conference, meetup, or online, you may find that you don't have the problems that a tool is designed to solve.&lt;/p&gt;

&lt;p&gt;Poorly configured tools also contribute to another major symptom: outages.&lt;/p&gt;

&lt;h1&gt;
  
  
  Frequent outages
&lt;/h1&gt;

&lt;p&gt;Outages should be a rare event, happening only after an external incident or a confluence of factors. In a healthy environment, outages are followed by postmortem that ends with process or infrastructure changes to prevent the same incident from recurring. A prerequisite of an effective postmortem, however, is a deep understanding of what went wrong and what changes are possible. Shallow knowledge of your tools limits both of these. If an outage was resolved by turning it off and back on again, the opportunity to learn from it is usually lost.&lt;/p&gt;

&lt;p&gt;Outages generally come in a few different flavors. They could be caused by performance problems, failed deployments, or If your team has a long cycle time, it becomes prohibitively time-consuming to polish off the small bugs at the end of a unit of work. These bugs accumulate, eventually leading to a crash in production or an invalid deployment. Worse yet, these same issues impair your ability to get the service up and running again. It's a cycle that feeds itself, and teams or companies that are not able to address the fundamental issues may end up spiraling to their death.&lt;/p&gt;

&lt;h1&gt;
  
  
  Excessively rigid process
&lt;/h1&gt;

&lt;p&gt;Especially as you gain expertise and advance in your career, you need to have a certain degree of flexibility in completing your work. Prioritization will never be perfect and you'll always find issues in the code you touch. It's rare that invisible concerns like performance, maintainability, and supporting infrastructure bubble to the top of a product manager's priorities. Well-operated organizations will typically have engineering leadership to balance this tension, but often it falls to you, an individual developer.&lt;/p&gt;

&lt;p&gt;A restrictive process may be a knee-jerk response put in place after features were repeatedly delayed (often due to long cycle times) or frequent outages. If developers don't balance features and internal work, the process may be a way to force features to be prioritized. The process may also be a band-aid over fragile build tools as well—"just follow the process to the T and it'll all be okay."&lt;/p&gt;

&lt;p&gt;It's also a symptom of problems within the leadership. Rigid process and micromanagement might be due to inexperienced managers, or those self-conscious about their level of contribution.&lt;/p&gt;

&lt;h1&gt;
  
  
  Leadership without obvious contributions
&lt;/h1&gt;

&lt;p&gt;It should be apparent what role the leaders of your team play when you look for it. A project manager should facilitate the creation and prioritization of tasks, making sure they contain the information you need to complete it. A tech lead should ensure that the process and tools being used enable you to ship code quickly and without error. A product manager should verify that what's being built meets the end-users' needs. It may not be obvious from where you sit, depending on your role within the team, but each of these individuals should be furthering the team's goals in their own way.&lt;/p&gt;

&lt;p&gt;If, when talking to coworkers and those above you in the organization, nobody can quite articulate what it is the people leading a team are contributing, the team has a major leadership problem. When those in charge of decisions abdicate their responsibilities, the process and technology begin to break down. Over time, the project may become mired in tech debt, waste people's time as they track down information, or ship features that nobody uses.&lt;/p&gt;

&lt;p&gt;Often, these types of leaders are struggling within their defined role. Unfortunately, a relatively common form of this manifests as bad success metrics for the team as a whole.&lt;/p&gt;

&lt;h1&gt;
  
  
  Organizational metrics unrelated to outcomes
&lt;/h1&gt;

&lt;p&gt;Objects and Key Results (OKRs) and Key Performance Indicators (KPIs) are two buzzwords that became popular after the publication of books of the same name. The ideas behind them are excellent: organizations should measure that their efforts are working. However, if these OKRs or KPIs don't relate to positive outcomes for the team or organization, then they're simply irrelevant numbers being used to micromanage developers.&lt;/p&gt;

&lt;p&gt;Unfortunately, this is often out of your control as an individual contributor. It may even be out of your purview, and they may be locked in for the quarter or even for the year. Misalignment between key metrics and actual, useful software is a major problem for the organization.&lt;/p&gt;




&lt;h1&gt;
  
  
  Responding to these problems
&lt;/h1&gt;

&lt;p&gt;These problems happen at companies of all sizes and are often deeply rooted in the culture that a team has grown around. There aren't one-size-fits-all solutions to these problems, and recognizing dysfunction isn't enough to fix it. Ultimately, many of the solutions to these problems require either buy-in or changes from management, which can be hard to effect when you're a few rungs down from them. &lt;/p&gt;

&lt;p&gt;One important thing to keep in mind is that individual contributors are usually first to feel the effects of these breakdowns. At an otherwise healthy company, those in charge may know that something is wrong, but not have the information they need to diagnose the problem. If any of these resonate with you, they would make good conversations to have during a one-on-one with your manager. &lt;/p&gt;

&lt;p&gt;If an organization is unable or unwilling to change, it may be a sign to freshen up your resume and begin exploring your options. It's easy to mistake the problems of one team with problems that are organization-wide, though. If you encounter problems like these, talk with coworkers on other teams about their experience. They may be able to help you resolve them, or you might be able to move within the company.&lt;/p&gt;




&lt;p&gt;Thanks for reading! I'm on Twitter as &lt;a href="https://twitter.com/cvitullo" rel="noopener noreferrer"&gt;@cvitullo&lt;/a&gt; (but most other places I'm vcarl). I moderate &lt;a href="http://join.reactiflux.com/" rel="noopener noreferrer"&gt;Reactiflux&lt;/a&gt;, a chatroom for React developers (check out &lt;a href="https://discord.gg/s6dJcJt" rel="noopener noreferrer"&gt;#jobs-advice&lt;/a&gt;!) and &lt;a href="https://discordapp.com/invite/vUsrbjd" rel="noopener noreferrer"&gt;Nodeiflux&lt;/a&gt;, a chatroom for Node.JS developers. If you have any questions or suggestions, reach out!&lt;/p&gt;

</description>
      <category>career</category>
      <category>beginners</category>
      <category>learning</category>
    </item>
    <item>
      <title>Everything you need to know about React Hooks</title>
      <dc:creator>Carl Vitullo</dc:creator>
      <pubDate>Thu, 25 Oct 2018 16:57:15 +0000</pubDate>
      <link>https://dev.to/vcarl/everything-you-need-to-know-about-react-hooks-doh</link>
      <guid>https://dev.to/vcarl/everything-you-need-to-know-about-react-hooks-doh</guid>
      <description>&lt;p&gt;React just announced a new feature: &lt;a href="https://reactjs.org/docs/hooks-overview.html" rel="noopener noreferrer"&gt;Hooks&lt;/a&gt;. It's a brand new set of APIs that enables powerful new ways to share stateful logic between components, optimize performance without significant rewrites, get some of the benefits of Redux-style separation of concerns, and more. They also deliver on a promise that the React team made years ago—stateful function components. Using state from function components came up as a possibility in &lt;a href="https://www.reactiflux.com/transcripts/dan-abramov/" rel="noopener noreferrer"&gt;Dan Abramov's Q&amp;amp;A on Reactiflux&lt;/a&gt; all the way back in April 2016.&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%2Fi.imgur.com%2FvIcMPdc.png" 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%2Fi.imgur.com%2FvIcMPdc.png" alt="Screenshot of Dan Abramov's Q&amp;amp;A transcript. The highlighted section reads, "&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It's been a long time coming, but they're here! More than just state, though, there are 11 new functions in all that should enable the full range of functionality that we use classes and the lifecycle for today.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;useState&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;useEffect&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;useContext&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;useCallback&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;useMemo&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;React.memo&lt;/code&gt; (Not a hook, but new)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;useReducer&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;useRef&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;useLayoutEffect&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;useImperativeMethods&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;useMutationEffect&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's take a look at what each of them is for.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;useState&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Stateful function components are enabled with the new function &lt;code&gt;useState&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;useState&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;SomeComponent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;props&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;state&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="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;initialState&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="nx"&gt;state&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;input&lt;/span&gt; &lt;span class="nx"&gt;onChange&lt;/span&gt;&lt;span class="o"&gt;=&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="nf"&gt;setState&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;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt; &lt;span class="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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you ever used the library &lt;code&gt;recompose&lt;/code&gt;, this API may look familiar. &lt;code&gt;useState&lt;/code&gt; takes an initial state as an argument, and returns the current state and an updater function. The &lt;code&gt;setState&lt;/code&gt; it returns is &lt;em&gt;almost&lt;/em&gt; the same used by class components—it can accept a callback that gets the current state as an argument, but it doesn't automatically merge top-level object keys.&lt;/p&gt;

&lt;p&gt;Each call to &lt;code&gt;useState&lt;/code&gt; is paired with a component, with its state persisting across renders. This means that you can call &lt;code&gt;useState&lt;/code&gt; multiple times within a single function component to get multiple independent state values. Because the &lt;code&gt;setState&lt;/code&gt; returned isn't scoped to a single component, we can define stateful behaviors independent of the component. This enables powerful new ways to abstract stateful logic. &lt;/p&gt;

&lt;p&gt;Let's look at an example that I've run into on several projects: managing sort state in several components. I find the APIs that table components expose to be inflexible, so I tend to write tables of data as one-offs. My current project has some code for managing what key to sort against, and in which direction, copy-pasted into several different components. With &lt;code&gt;useState&lt;/code&gt;, we gain the ability to define it as a separate module.&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;useSort&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;someArray&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;initialSortKey&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;state&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="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;isAscending&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;sortKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;initialSortKey&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="c1"&gt;// Let's pretend `makeSortComparator` exists for simplicity&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;comparator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;makeSortComparator&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;sortedData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;someArray&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;sort&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;comparator&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="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;sortedData&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;toggleAscending&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="nf"&gt;setState&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;=&amp;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="na"&gt;isAscending&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&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;isAscending&lt;/span&gt;
      &lt;span class="p"&gt;})),&lt;/span&gt;
    &lt;span class="na"&gt;setSortKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;sortKey&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
      &lt;span class="nf"&gt;setState&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;=&amp;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;sortKey&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;Now we have a reusable method to use in our data table components. We have a simple API we can use across our many different tables, with each component working off its own separate 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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;SomeTable&lt;/span&gt; &lt;span class="o"&gt;=&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="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;sortedData&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;sortControls&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useSort&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;id&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;table&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;TableHeading&lt;/span&gt; &lt;span class="p"&gt;{...&lt;/span&gt;&lt;span class="nx"&gt;sortControls&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="nx"&gt;tbody&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;sortedData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;datum&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;TableRow&lt;/span&gt; &lt;span class="p"&gt;{...&lt;/span&gt;&lt;span class="nx"&gt;datum&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="sr"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="err"&gt;}
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/tbody&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;/table&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;Please note: the React team strongly recommends prefixing the names of these types of modules with &lt;code&gt;use&lt;/code&gt; so there's a strong signal of what kind of behavior it provides. See &lt;a href="https://reactjs.org/docs/hooks-custom.html" rel="noopener noreferrer"&gt;the full docs&lt;/a&gt; for more about writing your own hooks.&lt;/p&gt;

&lt;p&gt;I am super excited about this new way to share functionality. It's much more lightweight than a HOC in all ways; less code to write, fewer components to mount, and fewer caveats. Check out the &lt;a href="https://reactjs.org/docs/hooks-reference.html#usestate" rel="noopener noreferrer"&gt;API documentation&lt;/a&gt; for all the details.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;useEffect&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;A lot of components have to kick off different types of effects as part of mounting or re-rendering. Fetching data, subscribing to events, and imperatively interacting with another part of the page are all common examples of this. But the code for handling these types of effects ended up scattered across &lt;code&gt;componentDidMount&lt;/code&gt;, &lt;code&gt;componentDidUpdate&lt;/code&gt;, and &lt;code&gt;componentWillUnmount&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;If you wanted to run the same effect when a prop changed, you either had to add a mess of comparisons in &lt;code&gt;componentDidUpdate&lt;/code&gt; or set a &lt;code&gt;key&lt;/code&gt; on the component. Using a &lt;code&gt;key&lt;/code&gt; simplifies your code, but it scatters control of effects into another file—completely outside the component's control!&lt;/p&gt;

&lt;p&gt;&lt;code&gt;useEffect&lt;/code&gt; simplifies all these cases. Imperative interactions are simple functions run after each render.&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;PageTemplate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;title&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;title&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;h1&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;title&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;/h1&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&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="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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For data fetching and other interactions you don't want to happen unnecessarily, you can pass an array of values. The effect is only run when one of these 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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ThingWithExternalData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;sort&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;state&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="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;({});&lt;/span&gt;
  &lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;axios&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`/our/api/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;?sortBy=&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;sort&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&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="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;sort&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;pre&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;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;state&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="mi"&gt;2&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;/pre&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;Subscriptions and other effects that require some kind of cleanup when the components unmount can return a function to run.&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;ThingWithASubscription&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;state&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="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;({});&lt;/span&gt;
  &lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;someEventSource&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;subscribe&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="nf"&gt;setState&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="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;someEventSource&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&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="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;pre&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;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;state&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="mi"&gt;2&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;/pre&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;This is so powerful. Just like with &lt;code&gt;useState&lt;/code&gt;, they can be defined as separate modules—not only does this put all the code required for these complex effects in a single location, &lt;em&gt;they can be shared across multiple components&lt;/em&gt;. Combined with &lt;code&gt;useState&lt;/code&gt;, this is an elegant way to generalize logic like loading states or subscriptions across components.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;useContext&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;The context API is great and was a significant improvement in usability compared to what existed before. It advanced context from a "you probably shouldn't use this" warning in the docs to an accepted part of the API. However, context can be cumbersome to use. It has to be used as a render prop, which is a pattern that doesn't compose gracefully. If you need values out of multiple different render props, you quickly end up indented to the extreme.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;useContext&lt;/code&gt; is a substantial step forward. It accepts the value created by the existing &lt;code&gt;React.createContext&lt;/code&gt; function (the same one you would pull &lt;code&gt;.Consumer&lt;/code&gt; off to use as a render prop) and returns the current value from that context provider. The component will rerender whenever the context value change, just like it would for state or props.&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;// An exported instance of `React.createContext()`&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;SomeContext&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./SomeContext&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;ThingWithContext&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;ourData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useContext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;SomeContext&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;pre&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;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ourData&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="mi"&gt;2&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;/pre&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;This gets rid of my final complaint with context. This API is simple and intuitive to the extreme and will be a powerful way to pipe state around an application.&lt;/p&gt;

&lt;h1&gt;
  
  
  More advanced hooks
&lt;/h1&gt;

&lt;p&gt;The 3 hooks mentioned above are considered to be the basic hooks. It's possible to write entire applications using only &lt;code&gt;useState&lt;/code&gt;, &lt;code&gt;useEffect&lt;/code&gt;, and &lt;code&gt;useContext&lt;/code&gt;--really, you could get away with just the first two. The hooks that follow offer optimizations and increasingly niche utility that you may never encounter in your applications.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;useCallback&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;React has a number of optimizations that rely on props remaining the same across renders. One of the simplest ways to break this is by defining callback functions inline. That's not to say that defining functions inline will cause performance problems--in many cases, it has no impact. However, as you begin to optimize and identify what's causing frequent re-renders, you may find inline function definitions to be the cause of many of your unnecessary prop change.&lt;/p&gt;

&lt;p&gt;In the current API, changing an inline function to something that won't change across renders can be a significant change. For function components, it means rewriting to a class (with all the changes that entails) and defining the function as a class method. &lt;code&gt;useCallback&lt;/code&gt; provides a simple way to optimize these functions with minimal impact on your code by memoizing a function provided to it. Just like &lt;code&gt;useEffect&lt;/code&gt;, we can tell it what values it depends on so that it doesn't change unnecessarily.&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;doSomething&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./doSomething&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;FrequentlyRerenders&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ExpensiveComponent&lt;/span&gt;
      &lt;span class="nx"&gt;onEvent&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;useCallback&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;doSomething&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;])}&lt;/span&gt;
    &lt;span class="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;This is another exciting improvement in usability. What used to mean a significant rewrite of a component can now be accomplished in-place with a function directly from React.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;useMemo&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;On the subject of optimizations, there's another hook that has me excited. Many times, I need to calculate derived data from the props I provide a component. It may be mapping an array of objects to a slightly different form, combining an array of data to a single value, or sorting or filtering. Often &lt;code&gt;render&lt;/code&gt; is the logical place for this processing to happen, but then it will be run unnecessarily whenever other props or state change. &lt;/p&gt;

&lt;p&gt;Enter &lt;code&gt;useMemo&lt;/code&gt;. It's closely related to &lt;code&gt;useCallback&lt;/code&gt;, but for optimizing data processing. It has the same API for defining what values it depends on as &lt;code&gt;useEffect&lt;/code&gt; and &lt;code&gt;useCallback&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ExpensiveComputation&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;sortComparator&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;filterPredicate&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;transformedData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useMemo&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="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;filterPredicate&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sort&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;sortComparator&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;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;sortComparator&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;filterPredicate&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;Table&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="o"&gt;=&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="sr"&gt;/&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;I'm excited about this for many of the same reasons as &lt;code&gt;useCallback&lt;/code&gt;. Previously, optimizing this type of processing typically meant extracting the logic to a separate function and memoizing that. Because it's common practices for memoization tools to rely on a functions &lt;em&gt;arguments&lt;/em&gt; for invalidating memoization, that meant creating a pure function. This refactoring can end up being too substantial, so only the most extreme performance problems end up being addressed. This hook should help avoid the "death by a thousand cuts" type of performance problems.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;React.memo&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;This isn't a hook, but it's a new API and an important optimization. Memoizing calculations and ensuring props don't change unnecessarily are good for performance, but both are more effective when combined with the &lt;code&gt;shouldComponentUpdate&lt;/code&gt; or &lt;code&gt;PureComponent&lt;/code&gt; features—neither of which is available for function components. &lt;/p&gt;

&lt;p&gt;&lt;code&gt;React.memo&lt;/code&gt; is a new function that enables behavior similar to &lt;code&gt;PureComponent&lt;/code&gt; for functions. It compares prop values and only re-renders when they change. It doesn't compare state or context, just like PureComponent. It can accept a second argument so you can do custom comparisons against props, but there's an important difference from &lt;code&gt;shouldComponentUpdate&lt;/code&gt;: it only receives props. Because &lt;code&gt;useState&lt;/code&gt; doesn't provide a single state object, it can't be made available for this comparison. &lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;useReducer&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;This hook has interesting implications for the ecosystem. The reducer/action pattern is one of the most powerful benefits of Redux. It encourages modeling UI as a state machine, with clearly defined states and transitions. One of the challenges to using Redux, however, is gluing it all together. Action creators, which components to &lt;code&gt;connect()&lt;/code&gt;, &lt;code&gt;mapStateToProps&lt;/code&gt;, using selectors, coordinating asynchronous behavior... There's a whole menagerie of associated code and libraries on top of Redux that can overwhelm. &lt;/p&gt;

&lt;p&gt;&lt;code&gt;useReducer&lt;/code&gt;, combined with the usability improvements to context, new techniques for memoizing calculations, and the hooks for running effects, allow for many of the same benefits as Redux with less conceptual overhead. I personally have never been bothered by the supposed boilerplate problem that Redux has, but considering how these hooks will combine has me excited for how features could be defined and scoped within an application.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;useRef&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Sometimes when writing components, we end up with information that we need to keep track of but don't want to re-render when it changes. The most common example of this is references to the DOM nodes we've created, for instance, an &lt;code&gt;input&lt;/code&gt; node that we need to track the cursor position for or imperatively focus. With class components we would track assign them directly to properties on &lt;code&gt;this&lt;/code&gt;, but function components don't have a context we can reference that way. &lt;/p&gt;

&lt;p&gt;&lt;code&gt;useRef&lt;/code&gt; provides a mechanism for these cases. It creates an object that exists for as long as the component is mounted, exposing the value assigned as a &lt;code&gt;.current&lt;/code&gt; property.&lt;/p&gt;

&lt;p&gt;Directly from &lt;a href="https://reactjs.org/docs/hooks-reference.html#useref" rel="noopener noreferrer"&gt;the docs&lt;/a&gt; (and &lt;a href="https://reactjs.org/docs/hooks-faq.html#is-there-something-like-instance-variables" rel="noopener noreferrer"&gt;the FAQ&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="c1"&gt;// DOM node ref example&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;TextInputWithFocusButton&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;inputEl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useRef&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&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;onButtonClick&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;// `current` points to the mounted text input element&lt;/span&gt;
    &lt;span class="nx"&gt;inputEl&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="nf"&gt;focus&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;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;input&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="nx"&gt;inputEl&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;text&lt;/span&gt;&lt;span class="dl"&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="nx"&gt;onButtonClick&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;Focus&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="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;span class="c1"&gt;// An arbitrary instance property&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Timer&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;intervalRef&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useRef&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;setInterval&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// ...&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="nx"&gt;intervalRef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;clearInterval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;intervalRef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;


&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This code is more verbose than using instance properties is in class components, but it should be relatively infrequent that you need to store values in this way. &lt;/p&gt;

&lt;h1&gt;
  
  
  Rarely used hooks
&lt;/h1&gt;

&lt;p&gt;The hooks mentioned above have covered all the use cases that I've encountered when writing applications. Reading through the docs of the remaining hooks, I understand why they exist and I'm sure that I'm using libraries that will implement them, but I don't anticipate using them myself in application code.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;useLayoutEffect&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;If I use any of these 3, I anticipate it will be &lt;code&gt;useLayoutEffect&lt;/code&gt;. This is the hook recommended when you need to read computed styles after the DOM has been mutated, but before the browser has painted the new layout.&lt;/p&gt;

&lt;p&gt;Crucially, this gives you an opportunity to apply animations with the least chance of visual artifacts or browser rendering performance problems. This is the method currently used by &lt;a href="https://github.com/joshwcomeau/react-flip-move" rel="noopener noreferrer"&gt;react-flip-move&lt;/a&gt;, an amazing transition library when items change position, but there might be situations where I need to use this myself.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;useImperativeMethods&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;To the best of my knowledge, this hook is a counterpart to &lt;code&gt;forwardRef&lt;/code&gt;, a mechanism for libraries to pass through the &lt;code&gt;ref&lt;/code&gt; property that would otherwise be swallowed. This is a problem for component libraries like Material UI, React Bootstrap, or CSS-in-JS tools like styled-components, but I haven't run into a case where I needed to solve this problem myself.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;useMutationEffect&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;This is the hook I'm having the hardest time wrapping my head around. It's run immediately before React mutates the DOM with the results from &lt;code&gt;render&lt;/code&gt;, but &lt;code&gt;useLayoutEffect&lt;/code&gt; is the better choice when you have to read computed styles. The docs specify that it runs before sibling components are updated and that it should be used to perform custom DOM mutations. This is the only hook that I can't picture a use case for, but it might be useful for cases like when you want a different tool (like D3, or perhaps a canvas or WebGL renderer) to take over the actual rendering of output. Don't hold me to that though.&lt;/p&gt;

&lt;h1&gt;
  
  
  In conclusion
&lt;/h1&gt;

&lt;p&gt;Hooks have me excited about the future of React all over again. I've been using this tool since 2014, and it has continually introduced new changes that convince me that it's the future of web development. These hooks are no different, and yet again substantially raise the bar for developer experience, enabling me to write durable code, and improve my productivity by extracting reused functionality.&lt;/p&gt;

&lt;p&gt;I thought Suspense was the only upcoming feature that I'd be excited for in 2018, but I'm happy to be proven wrong! Combined, I expect that React applications will set a new bar for end-user experience and code stability.&lt;/p&gt;




&lt;p&gt;Thanks for reading! I'm on Twitter as &lt;a href="https://twitter.com/cvitullo" rel="noopener noreferrer"&gt;@cvitullo&lt;/a&gt; (but most other places I'm vcarl). I moderate &lt;a href="http://join.reactiflux.com/" rel="noopener noreferrer"&gt;Reactiflux&lt;/a&gt;, a chatroom for React developers and &lt;a href="https://discordapp.com/invite/vUsrbjd" rel="noopener noreferrer"&gt;Nodeiflux&lt;/a&gt;, a chatroom for Node.JS developers. If you have any questions or suggestions, reach out! Cover image is from &lt;a href="https://unsplash.com/photos/kAwqA_yB_Fk" rel="noopener noreferrer"&gt;rawpixel on Unsplash&lt;/a&gt;&lt;/p&gt;

</description>
      <category>react</category>
      <category>javascript</category>
    </item>
    <item>
      <title>The Lerna license and ethics in software</title>
      <dc:creator>Carl Vitullo</dc:creator>
      <pubDate>Mon, 03 Sep 2018 19:09:50 +0000</pubDate>
      <link>https://dev.to/vcarl/the-lerna-license-and-ethics-in-software-1jf9</link>
      <guid>https://dev.to/vcarl/the-lerna-license-and-ethics-in-software-1jf9</guid>
      <description>&lt;p&gt;(Cover photo by &lt;a href="https://unsplash.com/photos/fHXP17AxOEk"&gt;Arto Marttinen&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;Earlier this week, Jamie Kyle and Daniel Stockman merged &lt;a href="https://github.com/lerna/lerna/pull/1616"&gt;a PR to Lerna&lt;/a&gt; adding a modified version of the MIT license. The modifications specified that certain companies were not granted a license to use the software due to their business contacts with ICE, (Immigration and Customs Enforcement, a US law enforcement agency). The rationale was given in the PR; ICE has been cruel to immigrants and refugees and Jamie wanted to use his position in open source to respond.&lt;/p&gt;

&lt;p&gt;I agree with his cause, though not his actions; ICE has crossed a line into brutality and abuse that can't be defended. However, Jamie's change &lt;a href="https://github.com/lerna/lerna/pull/1633"&gt;was quickly reverted&lt;/a&gt;. This is not a summary or reaction piece—his actions have already been debated and rehashed online, and I don't intend to pile on. It's made me think, though, about the ethics of creating software and our ability to shape the industry in which we spend our professional lives.&lt;/p&gt;

&lt;p&gt;While I agree with Jamie in principle, I disagree with his execution. I think he would have accomplished more if he had built support for his plan before merging the new license. It is not enough to act alone when protesting the actions of large organizations. The odds that a single open source contributor could successfully pressure Microsoft and Palantir, a company that has raised two billion dollars, into severing their contracts related to ICE, a federal law enforcement agency, were low. The outcome does not surprise me.&lt;/p&gt;

&lt;blockquote&gt;
&lt;h2&gt;
  
  
  It is not enough to act alone when protesting the actions of large organizations
&lt;/h2&gt;
&lt;/blockquote&gt;

&lt;p&gt;Our individual moral compasses can't be the only thing that guides us, because we have very little leverage to enforce our beliefs. We as an industry have no shared code of ethics; nobody to whom we can report violations. No license or certification to give our statements weight, beyond our own reputation. In many ways, the low barrier to entry is what makes software development great, but it means we have limited protection against unethical behavior by our employers.&lt;/p&gt;

&lt;p&gt;In other fields of engineering, there are professional societies or engineering unions. The National Society of Professional Engineers (NSPE) includes &lt;a href="https://www.nspe.org/resources/ethics/code-ethics"&gt;a code of ethics&lt;/a&gt; that members must abide by, backed by the organization itself. Members receive a title of "Professional Engineer," which is widely respected in the industry, and are expected to report ethical violations (by other engineers or their employers) to the organization for review.&lt;/p&gt;

&lt;p&gt;The fundamental canons listed in the NSPE code of ethics resonated with me:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I. Fundamental Canons&lt;/p&gt;

&lt;p&gt;Engineers, in the fulfillment of their professional duties, shall:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Hold paramount the safety, health, and welfare of the public.&lt;/li&gt;
&lt;li&gt;Perform services only in areas of their competence.&lt;/li&gt;
&lt;li&gt;Issue public statements only in an objective and truthful manner.&lt;/li&gt;
&lt;li&gt;Act for each employer or client as faithful agents or trustees.&lt;/li&gt;
&lt;li&gt;Avoid deceptive acts.&lt;/li&gt;
&lt;li&gt;Conduct themselves honorably, responsibly, ethically, and lawfully so as to enhance the honor, reputation, and usefulness of the profession.&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;

&lt;p&gt;Violations of these ethics have cost lives or endangered the public. In 1981, &lt;a href="https://en.wikipedia.org/wiki/Hyatt_Regency_walkway_collapse#Investigation"&gt;a hotel walkway collapsed&lt;/a&gt; because design changes had been approved without proper review. The Challenger space shuttle failed because &lt;a href="http://freakonomics.com/2011/06/01/launching-into-unethical-behavior-lessons-from-the-challenger-disaster/"&gt;an engineer's manager overruled his recommendation&lt;/a&gt; to delay the launch. In 2002, &lt;a href="https://en.wikipedia.org/wiki/Davis%E2%80%93Besse_Nuclear_Power_Station#2002_reactor_head_hole"&gt;a nuclear power plant nearly failed&lt;/a&gt; because engineers signed off on falsified inspection reports.&lt;/p&gt;

&lt;p&gt;Software development comes with a different set of ethical issues. Most of the software we encounter in our day-to-day would not put our lives at risk if it were to fail. The ethical quandaries in software engineering are more frequently about the &lt;em&gt;success&lt;/em&gt; of projects, not about minimizing the risk of failure. Software, and its impact on society, is still new, and we're still figuring out what is destructive.&lt;/p&gt;

&lt;blockquote&gt;
&lt;h2&gt;
  
  
  The ethical quandaries in software engineering are more frequently about the &lt;em&gt;success&lt;/em&gt; of projects
&lt;/h2&gt;
&lt;/blockquote&gt;

&lt;p&gt;The professional organizations most closely related to our field are the Institute of Electrical and Electronics Engineers (IEEE) and the Association for Computing Machinery (ACM), both of which have ethical codes on their website (&lt;a href="https://www.ieee.org/content/dam/ieee-org/ieee/web/org/about/ieee_code_of_conduct.pdf"&gt;IEEE's&lt;/a&gt; and &lt;a href="https://www.acm.org/code-of-ethics"&gt;ACM's&lt;/a&gt;). But neither of these organizations has had a strong presence in my career thus far, and neither code of ethics has much to say on the unique capacity software has to influence people's lives. The ACM ethical code is much, much more detailed than IEEE's, but the sections on avoiding harm and protecting privacy are insufficient to provide guidance on the ethical questions in software today.&lt;/p&gt;

&lt;p&gt;Is it ethical for Facebook to gather and sell the volume of data that they do? Facebook has made changes to the data it sells to its customers, but only after the question of government regulation was raised. Facebook has exceptionally fine-grained knowledge about its users' behavior and preferences, which it exposes to its advertising customers largely unfiltered. Is it ethical to allow advertisers such laser focus for their campaigns?&lt;/p&gt;

&lt;p&gt;Is it ethical for YouTube to suspend channels without warning because of copyright claims? Google has infamously poor customer service, despite an increasing number of people relying on their platform for their livelihood. Does Google have an ethical responsibility to improve their process? Or is the ethical onus on content providers to be more diligent when identifying infringing videos?&lt;/p&gt;

&lt;p&gt;It's clearly unethical for car manufacturers to cheat emissions tests—yet &lt;a href="https://en.wikipedia.org/wiki/Diesel_emissions_scandal#Manufacturers"&gt;Volkswagen, Chrysler, Jeep, Nissan, Renault, and Mercedes&lt;/a&gt; were all found to be using software to do so. Skirting regulations is illegal and automotive manufacturers were penalized for their emissions cheating, but that unethical behavior is not present in other their areas of engineering. I posit that this is because of the lack of a code of ethics for software engineering.&lt;/p&gt;

&lt;p&gt;It takes strength to take a stand for what you believe in and do something controversial, and I applaud Jamie's courage for his attempt with Lerna. But to have real, lasting impact on unethical behavior, we have to do more than take individual action. We need to lay some ground rules for what we as developers consider to be ethical software development.&lt;/p&gt;

&lt;p&gt;We need a frank discussion of what ethical software development is, and we need a reference that we can use for guidance on whether a project is ethical. I'd love to see your thoughts on ethics in software in the comments, but I've also created a &lt;a href="https://discord.gg/bpCwzzx"&gt;Discord server&lt;/a&gt; and &lt;a href="https://github.com/vcarl/ethical-software/issues/1"&gt;a GitHub repository&lt;/a&gt; to capture discussions.&lt;/p&gt;

&lt;p&gt;What unethical behavior have you seen in the industry?&lt;/p&gt;

&lt;p&gt;If software development had a code of ethics, what would our fundamental canons be?&lt;/p&gt;

</description>
      <category>softwareengineering</category>
      <category>ethics</category>
    </item>
    <item>
      <title>Staying on top of new Javascript features</title>
      <dc:creator>Carl Vitullo</dc:creator>
      <pubDate>Mon, 27 Aug 2018 11:36:18 +0000</pubDate>
      <link>https://dev.to/vcarl/staying-on-top-of-new-javascript-features-5cad</link>
      <guid>https://dev.to/vcarl/staying-on-top-of-new-javascript-features-5cad</guid>
      <description>&lt;p&gt;(Cover photo by &lt;a href="https://unsplash.com/photos/e3iwXJhT3Zk" rel="noopener noreferrer"&gt;Andrew Charney&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;With modern JS tooling, we have an opportunity to use Javascript features before they are implemented in browsers or node. However, not all features are equal. Some are more likely than others to be integrated into the language. Some will undergo significant changes before being added, and some will be dropped altogether. If you're using that feature in your app, either of those can introduce big refactors. But how can you tell whether a feature is something you should use?&lt;/p&gt;

&lt;p&gt;New features are introduced by TC39, a committee responsible for maintaining the specification underlying Javascript. There is a complete list of proposed additions to the spec in the &lt;a href="https://github.com/tc39/proposals/" rel="noopener noreferrer"&gt;TC39 proposals repo&lt;/a&gt; on GitHub. This is &lt;em&gt;the&lt;/em&gt; canonical location for new features, the primary source. There is a well-defined process that proposals must go through, and learning more about that process will help you stay on the cutting edge. &lt;/p&gt;

&lt;p&gt;The &lt;a href="https://tc39.github.io/process-document/" rel="noopener noreferrer"&gt;TC39 Process document&lt;/a&gt; defines what steps a proposal must take. This document is the source of the various stages that each feature goes through, which you may know best from the various stage-X presets from Babel. These stages are called the "maturity stages." The table defining the stages is a quick read that will give you a ton of context for how much has gone into a given proposal.&lt;/p&gt;

&lt;p&gt;What does it mean to be "stage 1" though? If there's a Babel plugin for it, why shouldn't we use a feature? To answer that, let's walk through what the different stages mean.&lt;/p&gt;

&lt;h1&gt;
  
  
  TC39 maturity stages
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Stage 0
&lt;/h2&gt;

&lt;p&gt;Brand new proposals are referred to as "strawman" or "stage 0" proposals. Stage 0 has &lt;em&gt;very little&lt;/em&gt; significance. It means that somebody has formally proposed an idea to the committee—that's it. The process document notes that this stage has no restrictions and does not require an attempt at specifying behavior. TC39 maintains &lt;a href="https://github.com/tc39/proposals/blob/master/stage-0-proposals.md" rel="noopener noreferrer"&gt;a list of stage 0 proposals&lt;/a&gt;, some of which have not progressed towards standardization in 4 years, and several of which have been &lt;a href="https://github.com/tc39/proposals/blob/master/inactive-proposals.md" rel="noopener noreferrer"&gt;formally dropped&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Relying on stage 0 features in production apps is a gamble in the long run. So why have developers downloaded &lt;a href="https://www.npmjs.com/package/babel-preset-stage-0" rel="noopener noreferrer"&gt;the stage 0 Babel preset&lt;/a&gt; 740,000 times (at time of writing) in the past week? &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%2Fdxggi3a8zemh2y4av34d.PNG" 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%2Fdxggi3a8zemh2y4av34d.PNG" alt="A download chart for babel-preset-stage-0 showing 740,000 downloads this week"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Are you using it? ...should you be?&lt;/p&gt;

&lt;h2&gt;
  
  
  Stages 1-3
&lt;/h2&gt;

&lt;p&gt;These stages live &lt;a href="https://github.com/tc39/proposals" rel="noopener noreferrer"&gt;in the readme&lt;/a&gt; of the TC39 proposals repo. These are the features actively working their way through the process.&lt;/p&gt;

&lt;p&gt;Stages 1 and 2 require an attempt to specify the behavior of the proposed feature, but implementations are intended to be exploratory. The more complex the proposal, the more likely it is to change as it moves from stage 1 to 2 to 3. If you rely on a proposal whose behavior changes, you may be stuck with a significant rewrite if you ever want to update your build tools. &lt;/p&gt;

&lt;p&gt;A perfect example of this churn is the proposals to add "decorators" to Javascript. They gained a lot of popularity when a proposal hit stage 2 in 2016, but it has not progressed to stage 3 (as of mid-2018). The proposal has changed substantially, and some of the original use cases are no longer supported in updated proposals.&lt;/p&gt;

&lt;p&gt;Familiarizing yourself with the list of stage 3 proposals is the best way to keep track of what's around the corner in Javascript. A proposal advances to stage 3 once designated reviewers and ECMAScript editors have approved of the complete specification. It may already be usable in a browser and likely has a Babel transform. All implementations must adhere to the spec, and changes are unlikely.&lt;/p&gt;

&lt;p&gt;That's not to say that stage 3 proposals are guaranteed to advance. Features at earlier stages are less likely to enter the spec because of how much work it takes to completely specify the behavior and implement it in browsers. Features at stage 3 may be rejected because irreconcilable issues are discovered while implementing, or in the case of &lt;code&gt;Object.observe&lt;/code&gt;, because the feature was deemed unnecessary.&lt;/p&gt;

&lt;h2&gt;
  
  
  Stage 4
&lt;/h2&gt;

&lt;p&gt;Proposals that are considered complete and ready for formal inclusion in the spec advance to stage 4. These move to the &lt;a href="https://github.com/tc39/proposals/blob/master/finished-proposals.md" rel="noopener noreferrer"&gt;finished proposals&lt;/a&gt; section of the TC39 proposals repo. A large amount of work is required to advance from stage 3 to 4. There must be acceptance tests and must be implemented in 2 independent VMs.&lt;/p&gt;

&lt;h1&gt;
  
  
  Some history
&lt;/h1&gt;

&lt;p&gt;TC39 and the release process were created relatively recently. If it feels like Javascript has changed a lot in the past few years, you're not wrong. &lt;/p&gt;

&lt;h2&gt;
  
  
  Ecma International and ECMAScript
&lt;/h2&gt;

&lt;p&gt;Javascript is an implementation of a language specification called "ECMAScript," &lt;a href="https://tc39.github.io/ecma262/" rel="noopener noreferrer"&gt;ECMA-262&lt;/a&gt;. &lt;a href="https://www.ecma-international.org/" rel="noopener noreferrer"&gt;Ecma International&lt;/a&gt; is a European standards body similar to ISO. ECMAScript is why the abbreviation for new versions are ES5, ES6, etc. In 2015, they changed the process to an annual release cycle, coinciding with the release of ES6–this is why it's also called ES2015.  It's worth noting the gaps between new versions of ECMAScript. (I'd also like to note that those are the correct capitalizations; Ecma de-acronym-ized their name in 1994, but ECMAScript is still styled that way in the spec)&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;1999, ES3&lt;/li&gt;
&lt;li&gt;2009, ES5, originally ES3.1&lt;/li&gt;
&lt;li&gt;2015, ES2015, with annual releases ever since.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  ES6, ES2015, or ES Harmony
&lt;/h2&gt;

&lt;p&gt;ES2015 was a turning point for Javascript, both technically and with regards to future extensions. It introduced a laundry list of new features, enumerated in &lt;a href="https://old.babeljs.io/learn-es2015/" rel="noopener noreferrer"&gt;the old Babel docs&lt;/a&gt;, and was the first release under the new process.&lt;/p&gt;

&lt;p&gt;These features completely reinvented Javascript. The reasons behind the sudden explosion of new features are largely political, and I won't attempt to recap them in depth. The short version is that the evolution of ES5 was contentious. It was originally intended to be released as ES3.1, but the final version included some features from the unsuccessful ES4 revision. If you're interested, &lt;a href="https://www.ecma-international.org/activities/Languages/Language%20overview.pdf" rel="noopener noreferrer"&gt;the ES4 draft&lt;/a&gt; is good to skim through.&lt;/p&gt;

&lt;p&gt;Following ES5, ES2015 was the first release under a newly developed process, led by TC39 (&lt;a href="https://www.ecma-international.org/memento/tc39-rf-tg.htm" rel="noopener noreferrer"&gt;Technical Committee 39 of Ecma&lt;/a&gt;). It was the first release after the various factions reconciled and began working together again, hence the codename "Harmony."&lt;/p&gt;

&lt;p&gt;Because this new process has been working so smoothly, recent releases of ECMAScript have not been the significant overhauls that ES2015 were. Dr. Axel Rauschmayer's blog has excellent summaries of the new features introduced in each &lt;a href="http://2ality.com/2016/01/ECMAscript-2016.html" rel="noopener noreferrer"&gt;2016&lt;/a&gt; &lt;a href="http://2ality.com/2016/02/ECMAscript-2017.html" rel="noopener noreferrer"&gt;2017&lt;/a&gt;, and &lt;a href="http://2ality.com/2017/02/ECMAscript-2018.html" rel="noopener noreferrer"&gt;2018&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Modern Javascript
&lt;/h2&gt;

&lt;p&gt;These official releases have become less important. Babel enables us to use features months or years before they're officially released, and we may not use the native implementations for years afterward due to legacy browsers. Babel has moved to make it even easier for us to forget about this process with &lt;a href="https://babeljs.io/docs/en/babel-preset-env/" rel="noopener noreferrer"&gt;&lt;code&gt;babel-preset-env&lt;/code&gt;&lt;/a&gt;. By configuring it with what browsers you need to support, it will provide minimal transpilation and polyfills to use native implementations whenever possible. &lt;/p&gt;

&lt;p&gt;Babel has also moved to deprecate the &lt;code&gt;stage-x&lt;/code&gt; presets for reasons given in a &lt;a href="https://babeljs.io/blog/2018/07/27/removing-babels-stage-presets" rel="noopener noreferrer"&gt;blog post announcing the change&lt;/a&gt;. &lt;code&gt;babel-preset-env&lt;/code&gt; provides a much more developer-centric solution to the same problem, and is recommended instead of manually setting presets.&lt;/p&gt;




&lt;p&gt;Thanks for reading! I'm on Twitter as &lt;a href="https://twitter.com/cvitullo" rel="noopener noreferrer"&gt;@cvitullo&lt;/a&gt; (but most other places I'm vcarl). I moderate &lt;a href="http://join.reactiflux.com/" rel="noopener noreferrer"&gt;Reactiflux&lt;/a&gt;, a chatroom for React developers and &lt;a href="https://discordapp.com/invite/vUsrbjd" rel="noopener noreferrer"&gt;Nodeiflux&lt;/a&gt;, a chatroom for Node.JS developers. If you have any questions or suggestions, reach out!&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>beginners</category>
      <category>node</category>
    </item>
  </channel>
</rss>
