<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: JP Erasmus</title>
    <description>The latest articles on Forem by JP Erasmus (@jperasmus).</description>
    <link>https://forem.com/jperasmus</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%2F50719%2Faa3b2260-a2ab-4937-b567-1f84e4f4663a.JPG</url>
      <title>Forem: JP Erasmus</title>
      <link>https://forem.com/jperasmus</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/jperasmus"/>
    <language>en</language>
    <item>
      <title>The 80/20 of Flexbox</title>
      <dc:creator>JP Erasmus</dc:creator>
      <pubDate>Sun, 20 Oct 2019 20:16:06 +0000</pubDate>
      <link>https://forem.com/jperasmus/the-80-20-of-flexbox-3paa</link>
      <guid>https://forem.com/jperasmus/the-80-20-of-flexbox-3paa</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--2WEmxywX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/0%2AIqIsJ2qNj58O-1z_.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--2WEmxywX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/0%2AIqIsJ2qNj58O-1z_.png" alt="" width="800" height="313"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This article aims to explain the 20% of flexbox that you’ll use 80% of the time.&lt;/p&gt;

&lt;h3&gt;
  
  
  What is Flexbox?
&lt;/h3&gt;

&lt;p&gt;Flexbox is a way to describe how elements should be displayed inside another element. The outer element is called the &lt;em&gt;flexbox container&lt;/em&gt;, and the inner elements are known as &lt;em&gt;flexbox items&lt;/em&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  How does it work?
&lt;/h3&gt;

&lt;p&gt;A flexbox container is created by adding a &lt;code&gt;display&lt;/code&gt; CSS property with a value of &lt;code&gt;flex&lt;/code&gt; on it. Any direct child elements inside this container inherently become flex items. A flex item itself could also be a flex container for its child elements, but consider that as a completely isolated flexbox relationship. A flexbox relationship is always a single level deep between a parent element and one or more children.&lt;/p&gt;

&lt;p&gt;After declaring your flexbox container, all flex items will by default be placed horizontally next to one another, starting at the left and stretching to the height of the container.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--y4FDPsFD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/0%2AFG0VAQTo9NFNQTYA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--y4FDPsFD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/0%2AFG0VAQTo9NFNQTYA.png" alt="" width="800" height="600"&gt;&lt;/a&gt;The default Flexbox layout&lt;/p&gt;

&lt;h3&gt;
  
  
  Flexbox Container properties
&lt;/h3&gt;

&lt;p&gt;To dictate whether flex items should be laid out horizontally or vertically, you set the &lt;code&gt;flex-direction&lt;/code&gt; property to either &lt;code&gt;row&lt;/code&gt; (horizontal default) or &lt;code&gt;column&lt;/code&gt; (vertical). There are also reverse "row" and "column" options available that will lay items out horizontally, from right to left (&lt;code&gt;row-reverse&lt;/code&gt;) or vertically from bottom to top (&lt;code&gt;column-reverse&lt;/code&gt;), assuming you use a horizontal left to right writing mode.&lt;/p&gt;

&lt;p&gt;Assuming you use the default &lt;code&gt;flex-direction: row&lt;/code&gt; declaration. To specify how items should be placed on the horizontal axis (known as the &lt;em&gt;main axis&lt;/em&gt;), think about the justification options you normally have in a rich text editor, i.e. aligned left, aligned right or centered. In flexbox, you use the &lt;code&gt;justify-content&lt;/code&gt; property on the container to do the same. The default is &lt;code&gt;justify-content: flex-start&lt;/code&gt; that aligns the items at the start of your main axis. Other possible values are &lt;code&gt;flex-end&lt;/code&gt;, your best friend &lt;code&gt;center&lt;/code&gt;, and lesser-used &lt;code&gt;space-between&lt;/code&gt;, &lt;code&gt;space-around&lt;/code&gt; and &lt;code&gt;space-evenly&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--0RmXm1ai--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/0%2Ac3qjamm0zrZtIjo0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--0RmXm1ai--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/0%2Ac3qjamm0zrZtIjo0.png" alt="" width="800" height="1141"&gt;&lt;/a&gt;Justify Content Examples&lt;/p&gt;

&lt;p&gt;To specify how flex items should be placed vertically in the container, on what is known as the cross axis, you use the &lt;code&gt;align-items&lt;/code&gt; property. The available values are very similar to what you get for &lt;code&gt;justify-content&lt;/code&gt;, with a few exceptions: &lt;code&gt;flex-start&lt;/code&gt;, &lt;code&gt;flex-end&lt;/code&gt;, &lt;code&gt;center&lt;/code&gt;, &lt;code&gt;stretch&lt;/code&gt; and &lt;code&gt;baseline&lt;/code&gt;. By default flex items will &lt;em&gt;stretch&lt;/em&gt; the full height of the container. To place items at the top or bottom along the cross axis, use &lt;code&gt;flex-start&lt;/code&gt; or &lt;code&gt;flex-end&lt;/code&gt; respectively. Traditionally, it has been quite hard to vertically centre items using only CSS, but with flexbox, you set &lt;code&gt;align-items: center&lt;/code&gt; and call it a day. The &lt;code&gt;baseline&lt;/code&gt; option is worth knowing about, but you'll use less often. If you have neighbouring flex items containing different sized text and you want to align them based on the bottom of the text, use &lt;code&gt;baseline&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--vy3k366C--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/0%2ArZ_7nQs6Yk8Q3SLG.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--vy3k366C--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/0%2ArZ_7nQs6Yk8Q3SLG.png" alt="" width="800" height="1273"&gt;&lt;/a&gt;Align Items Examples&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Have you noticed that we’ve already catered for most layout requirements, and so far we didn’t specify a single CSS property on any flex item? Everything has been on the flex container. Amazing.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;With that said, if you need to align items individually, you can set the &lt;code&gt;align-self&lt;/code&gt; property on an item. It takes all the available values that the container's &lt;code&gt;align-items&lt;/code&gt; supports.&lt;/p&gt;

&lt;p&gt;It is worth mentioning again that all the examples so far assume a left-to-right writing mode and the default horizontal row flex-direction. When either of these change, the concepts remain the same, only your perspective changes. What I mean is that in a right-to-left writing mode using &lt;code&gt;flex-direction: column-reverse&lt;/code&gt;, items will be justified along the main axis from bottom to top, but now aligned along the cross axis from right to left.&lt;/p&gt;

&lt;p&gt;What I’ve found is that it is easier to grasp the fundamentals first using the standard &lt;code&gt;flex-direction: row&lt;/code&gt;. After that, you can swap the flexbox axes around in your mind to visualize how reversed columns would work.&lt;/p&gt;

&lt;p&gt;The last flexbox container property worth talking about is &lt;code&gt;flex-wrap&lt;/code&gt;. By default flex items will not wrap to a new row when they run out of horizontal space. They rather get very cosy and squash together as far as possible until the CSS layout engine decides that's enough.&lt;/p&gt;

&lt;p&gt;To tell these items rather wrap to a new row, set &lt;code&gt;flex-wrap: wrap&lt;/code&gt;. As I mentioned, the default is &lt;code&gt;flex-wrap: nowrap&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--554X7YWH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/0%2A1VL5s5v3-d_FQV9r.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--554X7YWH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/0%2A1VL5s5v3-d_FQV9r.png" alt="" width="800" height="545"&gt;&lt;/a&gt;Flex Wrap Examples&lt;/p&gt;

&lt;p&gt;That wraps up all the container properties that we’re going to talk about. The rest of the properties are all set for individual flex items.&lt;/p&gt;

&lt;h3&gt;
  
  
  Flexbox Item Properties
&lt;/h3&gt;

&lt;p&gt;The cosy behaviour of flex items to squash together can be overridden with the &lt;code&gt;flex-shrink&lt;/code&gt; property. This property dictates in what proportion an item should shrink inside the container when space becomes scarce. The default is &lt;code&gt;flex-shrink: 1&lt;/code&gt;, which means all items shrink equally. If one of the items is set to &lt;code&gt;flex-shrink: 2&lt;/code&gt; while the rest keep a value of &lt;code&gt;1&lt;/code&gt;, this item will shrink twice as fast. It is important to note that the value is a unitless value that represents the shrinkage proportion and not something like &lt;code&gt;10px&lt;/code&gt; or &lt;code&gt;50%&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--RjJ_6Bc---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/0%2AA9YBlfBJBlDfTx7B.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--RjJ_6Bc---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/0%2AA9YBlfBJBlDfTx7B.png" alt="" width="800" height="242"&gt;&lt;/a&gt;Flex Shrink Example&lt;/p&gt;

&lt;p&gt;In contrast to flex items’ cosy shrink behaviour, they tend to be slightly shy by nature and will not “occupy all spaces” if any free space is available. In more official terms, all flex items have a &lt;code&gt;flex-grow&lt;/code&gt; value of &lt;code&gt;0&lt;/code&gt; set, which restricts it from growing. Just as with &lt;code&gt;flex-shrink&lt;/code&gt;, &lt;code&gt;flex-grow&lt;/code&gt; is a unitless value that dictates in which proportion an item should grow within a container if any free space is available. It is important to note that if you have two flex items, one with a &lt;code&gt;flex-grow&lt;/code&gt; value of &lt;code&gt;1&lt;/code&gt; and the other of &lt;code&gt;2&lt;/code&gt;, that does not mean the one item will be twice as big as the other. It means, from all the available space (if any), the one will receive two portions and the other, one portion.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--s3p5W7-d--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/0%2A9YxP5m91233R2QaC.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--s3p5W7-d--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/0%2A9YxP5m91233R2QaC.png" alt="" width="800" height="242"&gt;&lt;/a&gt;Flex Grow Example&lt;/p&gt;

&lt;p&gt;The final flex item property we’ll cover is &lt;code&gt;flex-basis&lt;/code&gt;. You can think of &lt;code&gt;flex-basis&lt;/code&gt; as the width of an item along the main axis. This property needs to be set with any of the standard CSS units, for example &lt;code&gt;px&lt;/code&gt;, &lt;code&gt;rem&lt;/code&gt;, &lt;code&gt;%&lt;/code&gt;, &lt;code&gt;vw&lt;/code&gt;, etc. The default is &lt;code&gt;flex-basis: auto&lt;/code&gt; which means the item takes the width of the content it contains, similar to a &lt;code&gt;display: inline-block&lt;/code&gt; element.&lt;/p&gt;

&lt;p&gt;A caveat to this rule is when a &lt;code&gt;width&lt;/code&gt; is specified, in which case the &lt;code&gt;width&lt;/code&gt; would trump the default &lt;code&gt;flex-basis: auto&lt;/code&gt;. Another interesting thing to be aware of is that if you have a &lt;code&gt;min-width&lt;/code&gt; specified along with a non-default &lt;code&gt;flex-basis&lt;/code&gt;, the &lt;code&gt;min-width&lt;/code&gt; will always take precedence.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--TFegpDkd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/0%2ArcSZZ4Ry4ts0n0Wu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--TFegpDkd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/0%2ArcSZZ4Ry4ts0n0Wu.png" alt="" width="800" height="242"&gt;&lt;/a&gt;Flex Basis Example&lt;/p&gt;

&lt;p&gt;Of course, there is a lot more to flexbox, like shorthand syntax for some of the properties we looked at. Feel free to &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Flexible_Box_Layout"&gt;dig deeper&lt;/a&gt; once you’re comfortable with these.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Originally published at&lt;/em&gt; &lt;a href="https://jperasmus.me/posts/the-80-20-of-flexbox"&gt;&lt;em&gt;https://jperasmus.me&lt;/em&gt;&lt;/a&gt;&lt;em&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>css</category>
      <category>flexbox</category>
    </item>
    <item>
      <title>Quality-first UI Development</title>
      <dc:creator>JP Erasmus</dc:creator>
      <pubDate>Tue, 23 Jul 2019 20:23:11 +0000</pubDate>
      <link>https://forem.com/jperasmus/quality-first-ui-development-1b5n</link>
      <guid>https://forem.com/jperasmus/quality-first-ui-development-1b5n</guid>
      <description>&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%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2A5tk-YnLnjSIIqrgPhJaDeQ.jpeg" 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%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2A5tk-YnLnjSIIqrgPhJaDeQ.jpeg"&gt;&lt;/a&gt;Photo by &lt;a href="https://unsplash.com/@kyran12?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Kyran Aldworth&lt;/a&gt; on &lt;a href="https://unsplash.com/search/photos/focus?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the same spirit as &lt;a href="https://en.ryte.com/wiki/Mobile_First" rel="noopener noreferrer"&gt;mobile-first&lt;/a&gt; and &lt;a href="http://offlinefirst.org/" rel="noopener noreferrer"&gt;offline-first&lt;/a&gt;, I want to write about quality-first.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;It merely means: start with quality in mind and don’t make it an afterthought.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If we say we are professional developers, the quality of the systems we produce is our responsibility.&lt;/p&gt;

&lt;p&gt;Does this apply to you? Ask yourself these two questions:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Does the majority of the work you do revolve around software development? Not &lt;em&gt;coding&lt;/em&gt;, but &lt;em&gt;development&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;Are you paid to do it?&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If you answered “yes” to both these questions, congratulations, you are a professional! 🎉&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;You can let the imposter syndrome go, you made it!&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;No one knows everything. Not even close. We’re all still on the journey to master this craft. Everyone started with zero knowledge, zero experience.&lt;/p&gt;

&lt;p&gt;Now that we’ve established that quality is our responsibility let’s talk about it.&lt;/p&gt;

&lt;p&gt;We’re going to look at quality from two perspectives: UX &amp;amp; DX (user experience and developer experience)&lt;/p&gt;

&lt;p&gt;Instead of getting hung up about the correct definitions here, in light of this post, they mean quality from the perspective of the end-user and the developer.&lt;/p&gt;

&lt;p&gt;I would argue that good DX goes a long way in helping to produce good UX. If you don’t agree, let me know on &lt;a href="https://twitter.com/jpunk11" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  UX
&lt;/h3&gt;

&lt;p&gt;We all agree UX is essential. If users have a terrible experience, they’ll leave, and without users, what’s the point in what we build?&lt;/p&gt;

&lt;p&gt;To produce a good user experience, we need to understand our users and how they use our products.&lt;/p&gt;

&lt;p&gt;Some questions we need to ask about our users:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Who are they?&lt;/li&gt;
&lt;li&gt;From where are they?&lt;/li&gt;
&lt;li&gt;Which browsers do they use?&lt;/li&gt;
&lt;li&gt;Do they have any disabilities?&lt;/li&gt;
&lt;li&gt;Are they native English speakers?&lt;/li&gt;
&lt;li&gt;What type of devices are they using?&lt;/li&gt;
&lt;li&gt;How stable are their internet connections?&lt;/li&gt;
&lt;li&gt;What time of day do they typically use the product?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You get the point. Most of these you probably already think about, but if you’re not, now is an ideal time to start exercising those empathy muscles.&lt;/p&gt;

&lt;h3&gt;
  
  
  DX
&lt;/h3&gt;

&lt;p&gt;Developer Experience is focusing on the developers’ quality of life during the development process. A lot of DX comes down to tooling. These tools include the frameworks we choose to use, our IDE’s, browser developer tools, plugins, CI/CD processes and more.&lt;/p&gt;

&lt;p&gt;If you are a team lead, it is your responsibility to set your team up for a win. Make it hard for teammates to produce poor quality by adequately setting up build processes, linting, tests and deployments.&lt;/p&gt;

&lt;h3&gt;
  
  
  Accessibility
&lt;/h3&gt;

&lt;p&gt;Accessibility is sometimes a weird subject, and people get very vocal and defensive about it. It doesn’t need to be that way.&lt;/p&gt;

&lt;p&gt;When you hear accessibility, most people think about blind people, but it is about a lot more. It is about real people with real lives and how we, as developers cater to these humans, our users. It is about the web being accessible to as many people as possible. No other platform can do that.&lt;/p&gt;

&lt;p&gt;According to the &lt;a href="https://www.worldbank.org/en/topic/disability" rel="noopener noreferrer"&gt;World Bank Group&lt;/a&gt;, 1 billion people, or 15% of the world’s population, experiences some form of disability, with more than 100 million of them with a severe disability.&lt;/p&gt;

&lt;p&gt;To put that in perspective: IE11 currently has &lt;a href="https://caniuse.com/usage-table" rel="noopener noreferrer"&gt;2.75% global usage&lt;/a&gt;, and we’re building websites that work in it. If we care about this small percentage, why would we not cater to the 15% of people with disabilities? I’m not saying that the full 15% of people with disabilities use the web, but the good news is that these users aren’t using IE, that’s for sure. 🤗&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;We should not charge extra for accessibility. It is part of the quality that we, as professionals, should deliver.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4&gt;
  
  
  Some things to consider:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Can your app be navigated with only a keyboard?&lt;/li&gt;
&lt;li&gt;Is your app friendly to screen readers used by people with sight impairments?&lt;/li&gt;
&lt;li&gt;Does your app assume users can distinguish options solely based on colour?&lt;/li&gt;
&lt;li&gt;Is there enough contrast between your UI elements (text vs background colours, etc.)?&lt;/li&gt;
&lt;li&gt;Does the user prefer reduced motion?&lt;/li&gt;
&lt;li&gt;Do all your videos provide subtitles?&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  What can we do?
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Set up tools like ESlint that make us aware of obvious accessibility issues in our code&lt;/li&gt;
&lt;li&gt;Learn proper HTML semantics&lt;/li&gt;
&lt;li&gt;Learn about ARIA&lt;/li&gt;
&lt;li&gt;Use browser and CLI tools to test accessibility issues&lt;/li&gt;
&lt;li&gt;Play with a screen reader&lt;/li&gt;
&lt;li&gt;Test navigating your app using only your keyboard&lt;/li&gt;
&lt;li&gt;Speak up when you notice UX that could be better. Don’t be a developer that only do what is given to you. Use your beautiful brain; you’re a professional, remember.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Security
&lt;/h3&gt;

&lt;p&gt;We’re not all working for the CIA, but there are some simple principles we can put in place to vastly improve security in our apps.&lt;/p&gt;

&lt;h4&gt;
  
  
  Things to consider
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Are all your pages served over HTTPS? There isn’t a good reason for your app not to use it anymore. Most hosting providers provide an SSL certificate for free. More than that, many web API’s and features like &lt;a href="https://developers.google.com/web/fundamentals/primers/service-workers/#you_need_https" rel="noopener noreferrer"&gt;Service Workers&lt;/a&gt; only work for sites served over HTTPS.&lt;/li&gt;
&lt;li&gt;Use HTTP headers like &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Strict-Transport-Security" rel="noopener noreferrer"&gt;HSTS&lt;/a&gt; and &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP" rel="noopener noreferrer"&gt;CSP&lt;/a&gt; to restrict your site from ever running over plain HTTP or loading any other resources on your page. With something as basic as this, you can almost eliminate most technical security issues.&lt;/li&gt;
&lt;li&gt;Is your app taking any user input? If so, make sure you sanitize everything. A good example is when writing HTML to the DOM using innerHTML. If the HTML string you're writing is coming from a user, they can effortlessly inject a script into your app. Expect the worst. It is suitable for a developer to be slightly cynical.&lt;/li&gt;
&lt;li&gt;Most of the time, the most significant gap in our security plans, is us, the humans involved. A solid philosophy to follow when it comes to security is the “&lt;a href="https://en.wikipedia.org/wiki/Principle_of_least_privilege" rel="noopener noreferrer"&gt;principle of least privilege&lt;/a&gt;”. It simply means to provide the minimum permissions needed to accomplish a task and nothing more. For instance, if a user should only be able to add a new entry, don’t give them delete permissions. At startups, when iterating quickly, this can be unnecessary red tape for your internal systems, but think about it and make a decision that suits your team the best.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Performance
&lt;/h3&gt;

&lt;p&gt;Performance is probably one of the most critical aspects of quality software that we can look at, both from a user’s and a developer’s point of view. Numerous studies have reported the financial gains, or losses companies have when seconds are shaven off from their app load times. We should, therefore, &lt;em&gt;optimize for performance&lt;/em&gt; as much as we can.&lt;/p&gt;

&lt;p&gt;We can also look at performance from the point of delivery: how long development of a feature takes. In other words, efficiency. Feature development is an area where faster isn’t always better for quality. On the other hand, slower also does not necessarily mean better quality. Tools can help us.&lt;/p&gt;

&lt;p&gt;Let’s face it; we are not good at repetitive tasks. When you’re moving fast, you can not possibly remember to check everything. Set up your tools beforehand to catch apparent mistakes, and when things slip through the cracks, update your tools for the next time. I use the term “tools” very loosely here. These tools can be code linters, unit tests, spell checkers, release checklists, etc.&lt;/p&gt;

&lt;p&gt;I’m personally not someone that would argue that a Computer Science degree is necessary to be a top-class developer. One thing I would say is that everyone should understand &lt;a href="https://rob-bell.net/2009/06/a-beginners-guide-to-big-o-notation/" rel="noopener noreferrer"&gt;Big-O notation&lt;/a&gt;. I’m not talking about heavy computer science theory, but as a way to think about the code you just wrote and how well it performs. Understand the difference between time complexity versus space complexity. A function can have O(1) time complexity, but be so extremely heavy in terms of space complexity that your user’s device runs out of memory. An O(1) function is useless in that scenario. With this said, Big-O is something to be aware of — if you’re thinking about it, you are already winning.&lt;/p&gt;

&lt;h3&gt;
  
  
  Communication
&lt;/h3&gt;

&lt;p&gt;I’m not going to say much about this, because we hear it all the time, communication is essential in most areas of our lives. Instead of quoting another cliché, let’s talk about one or 2 places where communication is important in our day to day jobs as developers:&lt;/p&gt;

&lt;h4&gt;
  
  
  Code Reviews
&lt;/h4&gt;

&lt;p&gt;Few communication tools make such a big difference, in the quality that we produce, as code reviews. I want to encourage you to note how you communicate on code reviews. As the person creating a pull request: are you clear about the intent of your code change? Use commit messages, PR descriptions, or before and after screenshots. These things go a long way in giving your reviewers some much-needed context.&lt;/p&gt;

&lt;p&gt;From a reviewers point of view, are you “listening” (paying attention) to the proposed code change? When you give feedback, are you merely nitpicking at a preferred code style or are you aiming to add value? A good thing to keep in mind is the concept of “ &lt;a href="https://www.radicalcandor.com/" rel="noopener noreferrer"&gt;Radical Candor&lt;/a&gt;”. It boils down to this: speak plainly but from a place of caring about the person and the product. It is healthy to disagree with and question a code implementation, but it is not cool doing that in a mean and condescending way. Luckily everyone at &lt;a href="https://www.goresponsive.com/" rel="noopener noreferrer"&gt;Responsive&lt;/a&gt; is generally pretty friendly, so this is rarely an issue. 🙂&lt;/p&gt;

&lt;h4&gt;
  
  
  Task Loggers
&lt;/h4&gt;

&lt;p&gt;When you write a task description or comment, be a human, think about the person that will be reading it. If that person is not another developer, don’t use all your tech jargon. If you’re writing things and the other person doesn’t understand you, are you communicating?&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Always aim for simplicity and clarity.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Testing
&lt;/h3&gt;

&lt;p&gt;I’ll be first to admit that testing is not always the most fun thing to do. No one makes hacker movies about testing; it just isn’t that sexy.&lt;/p&gt;

&lt;p&gt;There are probably as many opinions about the different types of testing as there are developers with right hands, so here’s mine for UI testing:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Not all types of testing are useful&lt;/li&gt;
&lt;li&gt;TDD does not work well for pure presentational components. It is much easier to add tests after the fact for this.&lt;/li&gt;
&lt;li&gt;Your tests should reflect how a user would interact with the UI as closely as possible — &lt;a href="https://twitter.com/kentcdodds/status/977018512689455106?lang=en" rel="noopener noreferrer"&gt;tweet inspiration&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Sometimes tests are not worth the time investment&lt;/li&gt;
&lt;li&gt;Sometimes tests will save your bacon&lt;/li&gt;
&lt;li&gt;Unit tests are beneficial for developers and not for stakeholders — stakeholders should not be concerned with code coverage. Developers should write enough unit tests for them to feel confident, rolling out quality code.&lt;/li&gt;
&lt;li&gt;Unit tests work best for pure logic-based functions&lt;/li&gt;
&lt;li&gt;There is a much higher ROI for end-to-end and integration tests than for unit tests. It is better to spend time setting up automated tests to cover the critical journeys in your application than to chase 100% test coverage for your unit tests.&lt;/li&gt;
&lt;li&gt;Tests should run as part of your CI process so that adding code to your main branches requires passing tests.&lt;/li&gt;
&lt;li&gt;Tests should be first-class code in your app and updated alongside the rest of your app code.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We now know that we want to put quality first, but how do we practically do that? We touched on many useful tools, but I want to take the rest of this post to chat about one particular tool that puts quality front and centre: &lt;a href="https://www.cypress.io/" rel="noopener noreferrer"&gt;Cypress.io&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Cypress
&lt;/h3&gt;

&lt;p&gt;Cypress.io is an open-source, front-end testing tool, built for the modern web.&lt;/p&gt;

&lt;h4&gt;
  
  
  Why Cypress?
&lt;/h4&gt;

&lt;p&gt;Cypress is most often compared to Selenium, but it is fundamentally different based on its architecture. Some of you, I know, have experience with tools like Chimp and Protractor that uses Selenium under the hood. Chimp uses WebDriver, which is Selenium.&lt;/p&gt;

&lt;p&gt;I’ll admit that writing BDD tests on CHEP was probably my least favourite part while I was on the project. Don’t get me wrong, the idea of automated UI tests excited me just as much as any other dev-nerd, but I sat most of the time debugging flakey tests. It just never seemed to do what I wanted. This led to zero confidence in the tool. What is the point in doing it if it doesn’t give us confidence in the app’s quality?&lt;/p&gt;

&lt;p&gt;Where Selenium and other similar tools interact with your application by sending commands from outside the browser, Cypress takes an entirely different approach and works directly within your browser.&lt;/p&gt;

&lt;h4&gt;
  
  
  Why is this great?
&lt;/h4&gt;

&lt;p&gt;Cypress can do things that Selenium simply can’t do. Things like mocking out network requests, setting items in local storage, and directly interacting with your app’s state. Selenium can only make educated guesses about your app’s state; Cypress knows intricately what is going on in your app.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;No more flake! No more pain!&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4&gt;
  
  
  Getting started
&lt;/h4&gt;

&lt;p&gt;Getting up and running with Cypress is extremely easy, so I won’t be covering it in this post. Install it from NPM and then to run it. Their &lt;a href="https://docs.cypress.io/guides/overview/why-cypress.html#In-a-nutshell" rel="noopener noreferrer"&gt;documentation&lt;/a&gt; is excellent — I encourage you to take a look.&lt;/p&gt;

&lt;p&gt;The first time you run the cypress open command, it will install Cypress itself and then open the interface. This UI is an Electron app, and like everything else about Cypress, it is 100% written in JavaScript.&lt;/p&gt;

&lt;p&gt;You can run Cypress with the UI Electron app or headless using the cypress run command. The headless option is useful for integrating Cypress into your CI pipeline.&lt;/p&gt;

&lt;h4&gt;
  
  
  Killer Features
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Time travel&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Realtime reloads&lt;/p&gt;

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

&lt;p&gt;Since Cypress runs inside the same browser context as your app, you can easily debug it with familiar tools. Drop a debugger straight in the code or console.log to your heart's content. Should I mention that since Selenium uses the same debug protocol as the browser developer tools, it is impossible to open the dev tools while it is running? It is crazy how we have been fine with this for so long.&lt;/p&gt;

&lt;p&gt;On top of that, Cypress gives you meaningful error messages.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Automatic waiting&lt;/li&gt;
&lt;li&gt;Spies, stubs, and clocks&lt;/li&gt;
&lt;li&gt;Network traffic control&lt;/li&gt;
&lt;li&gt;Consistent results&lt;/li&gt;
&lt;li&gt;Screenshots and videos&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I’ve been relatively harsh towards Selenium up until now. It is only fair to say that Selenium is a decent product that served its time well. In the past, before the era of JavaScript frameworks, web apps were a lot simpler. Every user action almost always resulted in a page refresh, which means there was little to no state that needed to be handled by the client. Today’s apps are incredibly complex, and we need new tools to help us make sense of it all. Cypress is such a tool.&lt;/p&gt;

&lt;h3&gt;
  
  
  Some links:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.cypress.io/guides/getting-started/installing-cypress.html" rel="noopener noreferrer"&gt;Installation and Setup&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.cypress.io/guides/getting-started/writing-your-first-test.html" rel="noopener noreferrer"&gt;Writing tests&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.cypress.io/guides/core-concepts/test-runner.html" rel="noopener noreferrer"&gt;Running tests&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.cypress.io/guides/guides/debugging.html" rel="noopener noreferrer"&gt;Debugging tests&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Originally published at&lt;/em&gt; &lt;a href="https://jperasmus.me/posts/quality-first-ui-development" rel="noopener noreferrer"&gt;&lt;em&gt;https://jperasmus.me&lt;/em&gt;&lt;/a&gt;&lt;em&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>cypress</category>
      <category>testing</category>
      <category>performance</category>
      <category>a11y</category>
    </item>
    <item>
      <title>The Web Developer’s Oath</title>
      <dc:creator>JP Erasmus</dc:creator>
      <pubDate>Tue, 18 Sep 2018 21:32:26 +0000</pubDate>
      <link>https://forem.com/jperasmus/the-web-developers-oath-39ae</link>
      <guid>https://forem.com/jperasmus/the-web-developers-oath-39ae</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--KPnGZJ7X--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AA2qZNV3Ah0uWIXnV_E9VCQ.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--KPnGZJ7X--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AA2qZNV3Ah0uWIXnV_E9VCQ.jpeg" alt=""&gt;&lt;/a&gt;Photo by &lt;a href="https://unsplash.com/photos/u26_RbawXyE?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;rawpixel&lt;/a&gt; on &lt;a href="https://unsplash.com/search/photos/promise?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For the longest time within the medical profession, new physicians have taken the &lt;a href="https://en.wikipedia.org/wiki/Hippocratic_Oath"&gt;Hippocratic Oath&lt;/a&gt; (or some variation of it) in which they swear to uphold a certain ethical standard. With the great responsibility resting on these individuals, it makes total sense to do this.&lt;/p&gt;

&lt;p&gt;As developers, our actions can sometimes have massive impact on other people’s lives, but yet ethics is not something discussed much in software development circles.&lt;/p&gt;

&lt;p&gt;What follows is an adaptation of the Hippocratic Oath, but for web developers:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;I swear to fulfill, to the best of my ability and judgment, this covenant:&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;I will respect the hard-won scientific gains of those developer giants whose blogs I’ve read, and gladly share such knowledge as is mine with those newbies who are to follow.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;I will apply, for the benefit of all project stakeholders, all linting rules that are required, avoiding those twin traps of over-engineering and premature optimizations.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;I will remember that there is art to web development as well as science, and that warmth, sympathy, and continuous learning may outweigh the developer’s current framework preference or build tools.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;I will not be ashamed to say “I know not,” nor will I fail to create a Stack Overflow question when the skills of another are needed for a project’s successful outcome.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;I will respect the privacy settings of my end users’ browsers, for their logins to my app are not disclosed to me to insecurely store in plain text. Most especially must I tread with care in matters of code reviews. If it is given me to approve a PR, all thanks. But it may also be within my power to decline the PR; this awesome responsibility must be faced with great humbleness and awareness of my own code under review. Above all, I must encourage diversity.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;I will remember that I do not style a button, implement an algorithm, but provide a digital experience, whose outcome may affect my users’ family and mental stability. My responsibility includes these related problems, if I am to care adequately for my craft.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;I will prevent bugs whenever I can, for continuous improvement is preferable to rewrites.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;I will remember that I remain a member of society, with special obligations to all my fellow nerds, those sound of mind and body as well as those suffering from imposter syndrome.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;If I do not violate this oath, may I enjoy fast internet and cross-browser consistency, respected while I code and remembered with affection when I become a project manager. May I always develop so as to preserve my end user’s valuable mobile data and may I long experience the joy of coding apps that are accessible as the open web ought to be.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In all seriousness, as a developer, next time you implement a new feature, create a GitHub issue, write a blog post or deliver a meetup talk, consider the impact of your actions on other people. Behind the code, there is a person.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>softwaredevelopment</category>
      <category>ethics</category>
      <category>webdev</category>
    </item>
    <item>
      <title>How to set Firebase security rules for your Flamelink project</title>
      <dc:creator>JP Erasmus</dc:creator>
      <pubDate>Thu, 13 Sep 2018 14:14:15 +0000</pubDate>
      <link>https://forem.com/jperasmus/how-to-set-firebase-security-rules-for-your-flamelink-project-23fn</link>
      <guid>https://forem.com/jperasmus/how-to-set-firebase-security-rules-for-your-flamelink-project-23fn</guid>
      <description>&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%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AGP0t7I3CXbma7EHrkk08JA.jpeg" 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%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AGP0t7I3CXbma7EHrkk08JA.jpeg"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So you are finally ready to take the training wheels off of your Flamelink project and take it live. Before you do that, have you set proper rules on your database? No really, you should!&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If this is the first time you are hearing about Flamelink, a CMS for Firebase, check out our &lt;a href="https://flamelink.io" rel="noopener noreferrer"&gt;website&lt;/a&gt; to get started. After linking up your Firebase project to Flamelink head back here to read about securing your content.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Not too long ago, a new Firebase project shipped in &lt;em&gt;test mode&lt;/em&gt;, ie. &lt;em&gt;reads&lt;/em&gt; and &lt;em&gt;writes&lt;/em&gt; were open to anyone on the real-time database. Since then the good folks at Firebase decided to change that and default to no read or write access in &lt;em&gt;locked mode&lt;/em&gt;. This was done because many developers never bothered to tighten security rules for their projects running in production, leaving their databases open to anyone.&lt;/p&gt;

&lt;p&gt;Now, Flamelink cannot work when your DB is in locked mode, because we would not be able to read/write to the DB from your browser. The only way to access your database in locked mode is from a server environment, which will require access via a service account. At Flamelink, we’ve decided against going that route and leave you, the end user, in full control of your project and the level of access you are comfortable in giving us while still sleeping at night. This comes at a cost in terms of the seamless user experience we can offer, and we might provide both options in the future, but I digress.&lt;/p&gt;

&lt;p&gt;To quickly get started with Flamelink we suggest you set the following database rules for the RTDB (real-time database):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;rules&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;flamelink&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;.read&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;auth != null&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;.write&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;auth != null&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;users&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;.indexOn&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;email&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="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="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In plain English, this reads:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;No access outside the “&lt;strong&gt;flamelink&lt;/strong&gt;” namespace BUT read and write access to authenticated users inside the “&lt;strong&gt;flamelink&lt;/strong&gt;” namespace.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;em&gt;The user’s index on the “email” and “id” fields are simply for better query performance and not important for this article on access control.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This is fine to quickly get started, but you can imagine it is not production-ready security to allow any authenticated user to write to your database. On the flip side, you might want some of the content to be readable by anyone regardless of whether they are logged in or not — think blog posts on your website, etc. So how can this be improved? Let’s look at a few options.&lt;/p&gt;

&lt;h4&gt;
  
  
  Things to know
&lt;/h4&gt;

&lt;p&gt;There are a few things to know about setting security rules for the RTDB:  &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Security rules are completely ignored when accessed from a server, they are only applied when accessed by a client — the browser
&lt;/li&gt;
&lt;li&gt;If a rule gives read/write access to a parent node any other child nodes further nested in the DB structure will also have access. In other words, you can’t set a rule to &lt;strong&gt;false&lt;/strong&gt; if it is already &lt;strong&gt;true&lt;/strong&gt; from a rule higher in the DB structure.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Watch this video for a really good introduction to the RTDB security rules if you are not already familiar:&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/PUBnlbjZFAI"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h4&gt;
  
  
  Read access for your app or website
&lt;/h4&gt;

&lt;p&gt;The easiest one is to give read access to anyone for non-sensitive content, so we’ll tackle that first.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;rules&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;flamelink&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;.read&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;auth != null&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;.write&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;auth != null&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;users&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;.indexOn&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;email&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;environments&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;$environment&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;content&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;nonSensitiveContentType&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
              &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;.read&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;  
            &lt;span class="p"&gt;}&lt;/span&gt;
          &lt;span class="p"&gt;}&lt;/span&gt;
          &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;schemas&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;.read&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
          &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What you need to notice is the “nonSensitiveContentType” property, which you can replace with your specific content type’s key. This is specific to your data, so take a look in your database. You can do this for as many of the content types as you like. If you want you can make all content readable as well by just setting:&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;content&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;.read&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is exactly what we’ve done for “schemas” in our example. If you use the official &lt;a href="https://flamelink.github.io/flamelink" rel="noopener noreferrer"&gt;Flamelink JavaScript SDK&lt;/a&gt;, you will have to give read access to “schemas”, since this is used to determine if fields are valid, relational and some other goodies like caching.&lt;/p&gt;

&lt;p&gt;Another option for read-access for your app users is to still require users to be authenticated but then use &lt;a href="https://firebase.google.com/docs/auth/web/anonymous-auth" rel="noopener noreferrer"&gt;Firebase’s anonymous sign-in&lt;/a&gt;. The benefit this would give you is that your DB will only be readable from within your app (or whether you allow authentication for your project) and not via the REST endpoints for instance.&lt;/p&gt;

&lt;h4&gt;
  
  
  Write access for specific users
&lt;/h4&gt;

&lt;p&gt;To restrict write access to your DB to only your Flamelink CMS users, you can specify the unique IDs (UID’s) in your rules like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;rules&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;flamelink&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;.read&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;auth != null&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;.write&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;auth.uid === '2TnyIXYi3FPeizykrJiLT972Oy53'&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;users&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;.indexOn&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;email&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can find the UID for your users under the “Authentication” section in your &lt;a href="https://console.firebase.google.com" rel="noopener noreferrer"&gt;Firebase console&lt;/a&gt;. You can very easily specify multiple UIDs as well:&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;.write&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;auth.uid === '2TnyIXYi3FPeizykrJiLT972Oy53' || auth.uid === 'LOkg1qVvLgTHWPyOkeBgrGaNuHy3'&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you decided to anonymously log in all your app users, you can further restrict writes by checking for the “anonymous” provider:&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;.write&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;auth.provider !== 'anonymous'&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Very dynamic rules
&lt;/h4&gt;

&lt;p&gt;&lt;em&gt;I want to start off, by saying that we do not suggest that you have to do this, but that it is possible. Continue…&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In Flamelink, users are assigned to Permission Groups, each with a unique ID. These permission groups map to certain permissions in the app. A permission group could, for instance, be configured to allow only “&lt;strong&gt;view&lt;/strong&gt;” access for schemas, but full &lt;a href="https://en.wikipedia.org/wiki/Create,_read,_update_and_delete" rel="noopener noreferrer"&gt;CRUD&lt;/a&gt; access for content. We can make use of these permission groups to dynamically restrict access on the database level.&lt;/p&gt;

&lt;p&gt;Bare with me, this might get nasty. We’ll first look at how we can enforce “&lt;strong&gt;view&lt;/strong&gt;” permissions on your content types, but the same technique can be used for any of the other CRUD actions.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;rules&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;flamelink&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;.read&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;auth != null&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;.write&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;auth != null&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;environments&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;$environment&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;content&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;$contentType&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
              &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;$locale&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;.read&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;auth != null &amp;amp;&amp;amp; root.child('flamelink').child('permissions').child(root.child('flamelink').child('users').child(auth.uid).child('permissions').val() + '').child('content').child($environment).child($contentType).child('view').val() === true&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
              &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
          &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Wow! What the heck?! Okay, let’s break that down because the idea is simple, the syntax not so much. I promise it will make sense.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The idea:&lt;/strong&gt; Get the user’s permission group and check if that permission group is set up to allow “view” permissions for the particular content.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The syntax:&lt;/strong&gt; The rule is made up of two parts: getting the permission group ID and then checking the permission configuration for that group.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;root&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;child&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;flamelink&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;child&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;users&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;child&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;uid&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;child&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;permissions&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;val&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This code starts at the root of your database and drills down to &lt;code&gt;flamelink.users.&amp;lt;uid&amp;gt;.permissions&lt;/code&gt;, where &lt;code&gt;&amp;lt;uid&amp;gt;&lt;/code&gt; is the user ID of the user trying to access the DB. The value of this database field is an integer, so we cast it to a string with &lt;code&gt;+ ''&lt;/code&gt; so that we can use it in the next part of our rule.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;root&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;child&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;flamelink&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;child&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;permissions&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;child&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;our&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;previous&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;query&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="nf"&gt;child&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;content&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;child&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;$environment&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;child&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;$contentType&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;child&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;view&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;val&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Again, we start at the root of the DB and drill down until we get to the actual permission group’s configuration: &lt;code&gt;flamelink.permissions.&amp;lt;user-permission-group&amp;gt;.content.&amp;lt;environment&amp;gt;.&amp;lt;content-type&amp;gt;.view&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Each permission group configuration consists of the following 4 boolean properties that map to a standard CRUD config:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;create:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;delete:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;update:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;  
  &lt;/span&gt;&lt;span class="err"&gt;view:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To check for any of the other permissions, simply replace “&lt;strong&gt;view&lt;/strong&gt;” with “&lt;strong&gt;update&lt;/strong&gt;”, “&lt;strong&gt;delete&lt;/strong&gt;” or “&lt;strong&gt;create&lt;/strong&gt;”.&lt;/p&gt;

&lt;p&gt;You might have also noticed the auth != null part at the beginning of the rule. That is to ensure we’re still checking that the user is logged in, otherwise, all our hard work would be undone by someone simply not logged in.&lt;/p&gt;

&lt;p&gt;That is it for the ".read" rule. The ".write" rule is similar to our reads, but more complex because we need to also take into account what the user is trying to do to the data to determine whether we should check the &lt;strong&gt;create&lt;/strong&gt;, &lt;strong&gt;update&lt;/strong&gt; or &lt;strong&gt;delete&lt;/strong&gt; config.&lt;/p&gt;

&lt;p&gt;We’re brave developers, so let’s continue.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;.write&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;auth !== null &amp;amp;&amp;amp;
    ((!data.exists() &amp;amp;&amp;amp;
      root
        .child('flamelink')
        .child('permissions')
        .child(
          root
            .child('flamelink')
            .child('users')
            .child(auth.uid)
            .child('permissions')
            .val() + ''
        )
        .child('content')
        .child($environment)
        .child($contentType)
        .child('create')
        .val() === true) ||
      (!newData.exists() &amp;amp;&amp;amp;
        root
          .child('flamelink')
          .child('permissions')
          .child(
            root
              .child('flamelink')
              .child('users')
              .child(auth.uid)
              .child('permissions')
              .val() + ''
          )
          .child('content')
          .child($environment)
          .child($contentType)
          .child('delete')
          .val() === true) ||
      (data.exists() &amp;amp;&amp;amp; newData.exists() &amp;amp;&amp;amp;
        root
          .child('flamelink')
          .child('permissions')
          .child(
            root
              .child('flamelink')
              .child('users')
              .child(auth.uid)
              .child('permissions')
              .val()
          )
          .child('content')
          .child($environment)
          .child($contentType)
          .child('update')
          .val() === true))&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now that we’ve ripped off the bandage, what is happening here?&lt;/p&gt;

&lt;p&gt;Apart from the &lt;code&gt;auth != null&lt;/code&gt; check for logged in users, there are 3 distinct parts to our rule, each dealing with a different action (create, delete and update).&lt;/p&gt;

&lt;p&gt;For our &lt;strong&gt;create&lt;/strong&gt; action we make use of Firebase’s &lt;code&gt;data.exist()&lt;/code&gt; method to check if no data currently exist for the particular content. That is how we know someone is trying to add new data.&lt;/p&gt;

&lt;p&gt;For our &lt;strong&gt;delete&lt;/strong&gt; action, we use the &lt;code&gt;newData.exists()&lt;/code&gt; method to check if new data would not exist. If the user’s action would result in no new data, we know they’re trying to delete something.&lt;/p&gt;

&lt;p&gt;For our last &lt;strong&gt;update&lt;/strong&gt; action, we combine the &lt;code&gt;data.exists()&lt;/code&gt; and &lt;code&gt;newData.exists()&lt;/code&gt; methods to determine that a user is trying to change existing data to something else.&lt;/p&gt;

&lt;p&gt;That was not so bad, was it?&lt;/p&gt;

&lt;p&gt;For a full example of how this can be applied, see this &lt;a href="https://gist.github.com/jperasmus/73741d5d86ad146b56b61f552786c167" rel="noopener noreferrer"&gt;gist&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This approach is not without its limitations. Since Flamelink is an evergreen and always-evolving product, new features are constantly added which could result in new nodes added to the database. If you tie down the database so much that we cannot make the necessary updates to your database structure, you won’t have access to the shiny new features. You can get around this by combining the UID specific rule we looked at earlier with this dynamic setup and ensure that if the user currently logged in is the owner of the project any writes can be made to the database. This would ensure that when new features are rolled out and the owner logged into the project, the necessary DB structure changes are applied.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;With this said, we very rarely make structural changes because of the evergreen nature of the product.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4&gt;
  
  
  Firebase Custom Claims
&lt;/h4&gt;

&lt;p&gt;We’ve left the best for last. The most eloquent solution is to use the lesser known feature of Firebase: &lt;a href="https://firebase.google.com/docs/auth/admin/custom-claims" rel="noopener noreferrer"&gt;Custom Claims&lt;/a&gt;. We would love to ship Flamelink with custom claims out of the box, but customs claims can only be set from a privileged server environment using the Firebase Admin SDK. What that means is that you, the project owner, will have to handle this yourself.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What are Custom Claims?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Simply put, custom claims are custom attributes set on user accounts. You can, for instance, set an isAdmin attribute on a user. This is very powerful because it provides the ability to implement various access control strategies, including role-based access control, in Firebase apps. The amazing thing is that these custom attributes can be used in your database’s security rules.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Some ideas on how we can use them&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Custom claims should only be used for access control and not to store any additional user data. It is best to store additional data in your database.&lt;/p&gt;

&lt;p&gt;When setting your custom claims, you can keep it simple and set an attribute called flamelinkUser on all your Firebase users which should have write access to content. Alternatively, you can set as elaborate claims at you would like, but bare in mind that the custom claims payload should not exceed a limit of a 1000 bytes. It is recommended to keep it as small as possible since these claims are sent along with all network requests and a big payload can have a negative performance impact.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How to use these custom claims in our security rules?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Once set, it is extremely easy to check for custom claims in our database security rules. All custom claims are set on the authenticated user’s auth token.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;rules&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;flamelink&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;.read&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;auth != null&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;.write&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;auth.token.flamelinkUser === true&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;How to set custom claims for your users?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The only requirement for setting custom claims is that they are set from a server environment using the Firebase Admin SDK, whether that is with a stand-alone Express server you have running or using &lt;a href="https://firebase.google.com/docs/functions/" rel="noopener noreferrer"&gt;Cloud Functions for Firebase&lt;/a&gt;, that is up to you. The code looks something like this (example uses JavaScript, but you can use any of the supported server side languages):&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;// import admin SDK&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;admin&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;firebase-admin&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// initialize admin app with any of the supported options&lt;/span&gt;
&lt;span class="nx"&gt;admin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;initializeApp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;\*&lt;/span&gt;&lt;span class="sr"&gt; config here &lt;/span&gt;&lt;span class="se"&gt;\*&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// create your custom claims object (whatever you want)&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;customClaims&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
  &lt;span class="na"&gt;flamelinkUser&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;  
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="c1"&gt;// set the custom claims object for given UID&lt;/span&gt;
&lt;span class="nx"&gt;admin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;setCustomUserClaims&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;uid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;customClaims&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;admin.auth().setCustomUserClaims()&lt;/code&gt; method returns a Promise. It is important to note that setting new custom claims overwrite any existing custom claims, so you might want to first retrieve the existing claims and update it before setting it again.&lt;/p&gt;

&lt;h4&gt;
  
  
  Conclusion
&lt;/h4&gt;

&lt;p&gt;Hopefully, this gave you an idea of how powerful and flexible Firebase security rules are. I encourage you to read more about these rules in &lt;a href="https://firebase.google.com/docs/database/security/" rel="noopener noreferrer"&gt;Firebase’s documentation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you have any other ideas on how we can improve these security rules, please let us know in the comments below or join our &lt;a href="https://flamelink.io/slack" rel="noopener noreferrer"&gt;Slack community,&lt;/a&gt; we’d love to have you.&lt;/p&gt;

</description>
      <category>flamelink</category>
      <category>security</category>
      <category>firebase</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Useful “reduce” use cases</title>
      <dc:creator>JP Erasmus</dc:creator>
      <pubDate>Tue, 28 Aug 2018 06:44:24 +0000</pubDate>
      <link>https://forem.com/jperasmus/useful-reduce-use-cases-929</link>
      <guid>https://forem.com/jperasmus/useful-reduce-use-cases-929</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ci-rSxc_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2Aji3NuzK3DyQUmg-NUBUtOQ.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ci-rSxc_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2Aji3NuzK3DyQUmg-NUBUtOQ.jpeg" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I recently saw a tweet from a developer stating that he understands the array reduce function, but can not think of many useful use cases for it. In this post, I’ll aim to give a couple of real-world use cases for reduce.&lt;/p&gt;

&lt;p&gt;The post will assume you are comfortable with JavaScript Promises; if not, I have a very &lt;a href="https://medium.com/@jperasmus11/roll-your-own-async-compose-pipe-functions-658cafe4c46f"&gt;simplified primer&lt;/a&gt; on them in a previous post that you can check out.&lt;/p&gt;

&lt;h3&gt;
  
  
  Promise chains
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;Promise.all()&lt;/code&gt; is very useful to run numerous promises in parallel, but what if the &lt;strong&gt;order&lt;/strong&gt; in which your promises should resolve is important? In that case, you need to run them sequentially. The following function will do exactly that.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;promiseQueue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;promiseFn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;list&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
  &lt;span class="nx"&gt;list&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;reduce&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;queue&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;item&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;queue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nx"&gt;result&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;itemResult&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;promiseFn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;item&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;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;concat&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nx"&gt;itemResult&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
    &lt;span class="p"&gt;}),&lt;/span&gt;
    &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;([])&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Sum numbers
&lt;/h3&gt;

&lt;p&gt;The most taught and classic example of using reduce is to get the total of an array of numbers, so this list won’t be complete without it. It doesn’t need to be an array of numbers though - you can use more complex data structures.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;cities&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;city&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Chongqing&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;population&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;30165500&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;city&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Shanghai&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;population&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;24183300&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;city&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Beijing&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;population&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;21707000&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;city&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Lagos&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;population&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;16060303&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="c1"&gt;// ...etc&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;totalPopulation&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;cities&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;reduce&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;city&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;sum&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;city&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;population&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Filter and Map
&lt;/h3&gt;

&lt;p&gt;When you have a data set that needs to be filtered by some criteria and you want to manipulate each remaining item as well, an okay, but slightly naive option would be to first run filter on it and then map over it again essentially doing a lot more looping-over-items than required. A better option would be to use reduce.&lt;/p&gt;

&lt;p&gt;Say for instance you have the results of all the students that wrote a particular paper, but you are only interested in the full names of all the students that had a mark of more than 80 out of a hundred.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;studentsData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;firstName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Albert&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;lastName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Einstein&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;score&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;53&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;firstName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Charles&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;lastName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Dickens&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
    &lt;span class="na"&gt;score&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;84&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;firstName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Marilyn&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;lastName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;vos Savant&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;score&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;99&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="c1"&gt;// etc.&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;smartestStudents&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;studentsData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;reduce&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;student&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;// do your filtering&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;student&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;score&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// do your mapping&lt;/span&gt;
    &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;student&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;firstName&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="nx"&gt;student&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;lastName&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="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;result&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;h3&gt;
  
  
  Array to Object conversion
&lt;/h3&gt;

&lt;p&gt;Sometimes you need an object as output from an array and not another array. All other array higher-order functions will &lt;em&gt;always&lt;/em&gt; produce an array as output.&lt;/p&gt;

&lt;p&gt;Say for instance you have an array of form fields with their validation constraints and you want an object of constraints where the name of the field is the top level keys in the object.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fields&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Title&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;title&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;constraints&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;required&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;^Title is required&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;allowEmpty&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="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Slug&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;slug&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;constraints&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;required&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;^Slug is required&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;allowEmpty&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;format&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;pattern&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;[a-z0-9&lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;&lt;span class="s1"&gt;_-]+&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;flags&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;i&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;^Can only be a valid slug&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="c1"&gt;// etc.&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;validationRules&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;fields&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;reduce&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;rules&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;field&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;assign&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;rules&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;field&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="nx"&gt;field&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;constraints&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 would produce something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;required&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nl"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;^Title is required&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;allowEmpty&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="p"&gt;},&lt;/span&gt;
  &lt;span class="nx"&gt;slug&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;required&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nl"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;^Slug is required&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;allowEmpty&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="nx"&gt;format&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nl"&gt;pattern&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;[a-z0-9&lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;&lt;span class="s1"&gt;_-]+&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;flags&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;i&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;^Can only be a valid slug&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="c1"&gt;// etc.&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Note: if you care about not mutating data, you might consider using &lt;code&gt;Object.assign({}, rules, { [field.name]: field.constraints })&lt;/code&gt; or using the object spread syntax, &lt;code&gt;{ ...rules, [field.name]: field.constraints }&lt;/code&gt;. I would advise against this. Personally, I’m a firm believer in the value of immutable data, but with pragmatism. In this case, a new object will be created for each iteration which could end up using quite a lot of unnecessary memory in your app.&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Piping or Composing functions
&lt;/h3&gt;

&lt;p&gt;Sometimes you have a sequence of functions that you want to be invoked for a specific value. The useful functional programming methods, &lt;code&gt;compose&lt;/code&gt; and &lt;code&gt;pipe&lt;/code&gt; are perfect for this, but unfortunately, they are not natively part of the JavaScript language (yet!). Not to worry, we can easily write our own:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;pipe&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(...&lt;/span&gt;&lt;span class="nx"&gt;fns&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;x&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;fns&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;reduce&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;v&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;f&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;f&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;v&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;code&gt;pipe&lt;/code&gt; is a function that takes a list of functions, calling each function in sequence with the output of the previous function used as the input for the next.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;compose&lt;/code&gt; is very similar; it just invokes the functions in reverse order, from last to first, so it can be implemented like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;compose&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(...&lt;/span&gt;&lt;span class="nx"&gt;fns&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;x&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;fns&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;reverse&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;reduce&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;v&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;f&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;f&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;v&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;An example could be calculating the checkout total for an online store:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;calculateTotal&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;pipe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;applyAnySales&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;minusStoreCredit&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;applyCouponCode&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;addTaxes&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;cardValue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;250&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;total&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;calculateTotal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cardValue&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;em&gt;If you have any other practical examples of using &lt;code&gt;reduce&lt;/code&gt; please leave a comment so that I can learn from you.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>functional</category>
      <category>higherorderfunc</category>
      <category>promises</category>
      <category>javascript</category>
    </item>
    <item>
      <title>“forEach” all the things!</title>
      <dc:creator>JP Erasmus</dc:creator>
      <pubDate>Fri, 11 May 2018 15:38:51 +0000</pubDate>
      <link>https://forem.com/jperasmus/foreach-all-the-things-53hg</link>
      <guid>https://forem.com/jperasmus/foreach-all-the-things-53hg</guid>
      <description>&lt;p&gt;&lt;em&gt;Disclaimer: this is an opinion piece, feel free to disagree.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Having done a good number of code reviews over the past few years and seeing what comes back to bite us vs. what generally works the way we intended, one such issue is knowing when to use &lt;code&gt;forEach&lt;/code&gt;. It comes down to asking yourself the right questions.&lt;/p&gt;

&lt;p&gt;On a separate but related point, I would argue that being comfortable with AND knowing when to use &lt;code&gt;forEach&lt;/code&gt;, &lt;code&gt;map&lt;/code&gt;, &lt;code&gt;filter&lt;/code&gt; or &lt;code&gt;reduce&lt;/code&gt;, you can tackle any array-related data manipulation problem, so it really pays, as a developer, putting in the effort to get very comfortable with it. Sure there are some other very useful methods, like &lt;code&gt;flatMap&lt;/code&gt;, but knowing these four, you can go a long way.&lt;/p&gt;

&lt;p&gt;This post will use JavaScript as an example, but the concept is the same for any language that supports the higher-order array functions: &lt;code&gt;forEach&lt;/code&gt;, &lt;code&gt;map&lt;/code&gt;, &lt;code&gt;filter&lt;/code&gt; and &lt;code&gt;reduce&lt;/code&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Who is this post for?
&lt;/h4&gt;

&lt;p&gt;Developers that already know to favour &lt;code&gt;forEach&lt;/code&gt; over &lt;code&gt;for&lt;/code&gt; loops to write more beautiful (declarative!) code, but are perhaps not comfortable with these higher-order array functions. There is a place for a &lt;code&gt;for&lt;/code&gt; loop, but more often than not, you should use the more declarative option.&lt;/p&gt;

&lt;h4&gt;
  
  
  “forEach” all the things!
&lt;/h4&gt;

&lt;p&gt;The first thing developers start doing when they move from the imperative for loop to more declarative forEach functions, is that they &lt;strong&gt;“forEach all the things”&lt;/strong&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%2Fcdn-images-1.medium.com%2Fmax%2F500%2F1%2A_HepUVzNXC4oo5jGsco_og.jpeg" 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%2Fcdn-images-1.medium.com%2Fmax%2F500%2F1%2A_HepUVzNXC4oo5jGsco_og.jpeg"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is okay and definitely better than using for loops everywhere, but we can do better.&lt;/p&gt;

&lt;h4&gt;
  
  
  The thinking process
&lt;/h4&gt;

&lt;p&gt;Sure you can use a shoe to hang a picture on the wall, but a hammer is a better tool for the job.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Use the right tool for the job.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;What follows are questions you can ask yourself while coding and trying to decide whether you should use &lt;code&gt;forEach&lt;/code&gt;, &lt;code&gt;map&lt;/code&gt;, &lt;code&gt;filter&lt;/code&gt; or &lt;code&gt;reduce&lt;/code&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  1. I’ve got an array of things and I want to manipulate each item in some way
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;The wrong way:&lt;/strong&gt; use forEach&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;list&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;a&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;b&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;c&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;newList&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;

&lt;span class="nx"&gt;list&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;item&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;newList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toUpperCase&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;newList&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// ['A', 'B', 'C']&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;The right way:&lt;/strong&gt; use map&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;list&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;a&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;b&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;c&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;newList&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;list&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;item&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toUpperCase&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;newList&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// ['A', 'B', 'C']&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  2. I’ve got an array of things and I want to “reduce” it to one thing
&lt;/h4&gt;

&lt;p&gt;This one is easy to remember once you are comfortable with it and it works really well for situations like summing totals or reducing a list of objects into a single object. You can think of &lt;code&gt;reduce&lt;/code&gt; as compressing a list of inputs into a single output.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The wrong way:&lt;/strong&gt; use forEach&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;total&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;list&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="nx"&gt;list&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;item&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;total&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;total&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;item&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;total&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// 10&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;The right way:&lt;/strong&gt; use reduce&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;list&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;total&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;list&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reduce&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;item&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;sum&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;total&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// 10&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This example, to sum a few numbers, doesn’t make the pain obvious, but working with more complex data will surface the problem.&lt;/p&gt;

&lt;h4&gt;
  
  
  3. I’ve got an array of things, but I only want a subset of them
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;The wrong way:&lt;/strong&gt; use forEach &lt;em&gt;(noticing a pattern here?)&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;list&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;evenNumbers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;

&lt;span class="nx"&gt;list&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="nx"&gt;evenNumbers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
 &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;evenNumbers&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;The right way:&lt;/strong&gt; use filter&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;list&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;evenNumbers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;list&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;item&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;item&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;evenNumbers&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  4. I’ve got an array of things and I want to perform an action for each item but I don’t care about a return value
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;The wrong way:&lt;/strong&gt; use map, filter or reduce&lt;/p&gt;

&lt;p&gt;Just like it is technically possible to use &lt;code&gt;forEach&lt;/code&gt; for everything else, as we saw above, it is possible to use any of the other higher-order functions here, but it would not be the right tool for the job.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“It is just semantics” is not a thing.&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&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;list&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;user1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;user2&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;user3&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;newList&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;list&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;user&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;fireAndForgetNetworkRequest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;newList&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// [undefined, undefined, undefined]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;The right way:&lt;/strong&gt; use forEach&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;list&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;user1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;user2&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;user3&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="nx"&gt;list&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;fireAndForgetNetworkRequest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="c1"&gt;// nothing to log&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Hint&lt;/strong&gt;: If you can’t declare your variables with &lt;em&gt;const&lt;/em&gt; and you need to use &lt;em&gt;let&lt;/em&gt;, you might be using the wrong method.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4&gt;
  
  
  TL;DR;
&lt;/h4&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%2Fcdn-images-1.medium.com%2Fmax%2F757%2F1%2A8AOqGSDe1pzNAb1nMrYOTA.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%2Fcdn-images-1.medium.com%2Fmax%2F757%2F1%2A8AOqGSDe1pzNAb1nMrYOTA.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you made it this far, hopefully, the post wasn’t too boring. Let me know in the comments if you disagree with anything or if you have some better examples that I haven’t thought of.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Published: 10 May 2018&lt;/em&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>functional</category>
      <category>higherorderfunc</category>
    </item>
  </channel>
</rss>
