<?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: Steven Washington</title>
    <description>The latest articles on Forem by Steven Washington (@washingtonsteven).</description>
    <link>https://forem.com/washingtonsteven</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%2F22665%2F0161b8ab-4d13-4fef-b5d6-03a8da31006b.jpg</url>
      <title>Forem: Steven Washington</title>
      <link>https://forem.com/washingtonsteven</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/washingtonsteven"/>
    <language>en</language>
    <item>
      <title>Understanding Permissions</title>
      <dc:creator>Steven Washington</dc:creator>
      <pubDate>Thu, 18 Jul 2019 10:39:38 +0000</pubDate>
      <link>https://forem.com/washingtonsteven/understanding-permissions-3mek</link>
      <guid>https://forem.com/washingtonsteven/understanding-permissions-3mek</guid>
      <description>&lt;p&gt;Every so often I’ll be setting up a project and run into file permission issues. Most times, I’ll Google the error and come across a forum post that’s something like&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Just type &lt;code&gt;chmod 755 ./file.txt&lt;/code&gt; in Terminal and you’ll be fine.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So while this works, it would be much better if I actually knew that this line was doing.&lt;/p&gt;

&lt;p&gt;The first part is easy: &lt;code&gt;chmod&lt;/code&gt; is the name of the process that actually changes the permissions on the file I want.&lt;/p&gt;

&lt;p&gt;The last part is even easier: It’s the path to the file I want to change the permissions on.&lt;/p&gt;

&lt;p&gt;But that’s that &lt;code&gt;755&lt;/code&gt; about? How does that relate to file permissions?&lt;/p&gt;

&lt;h2&gt;
  
  
  Unix permissions basics
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Very&lt;/em&gt; basically, file permission roles are broken up into 3 types of people: User, Group and World.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;User&lt;/strong&gt; is the owner of the file.&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Group&lt;/strong&gt; is a special set of users can have special privileges on the file.&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Others&lt;/strong&gt; is everyone else.&lt;/p&gt;

&lt;p&gt;Additionally, there are four types of permissions: Read, Write, Execute, and None. Read, Write and None are self explanatory. Having the “execute” permission means that you can run the file, as opposed to simply opening it or editing it. This is usually for files that are executable by the system like shell scripts or similar.&lt;/p&gt;

&lt;p&gt;For example: If you have Read and Write permissions for &lt;code&gt;./file.sh&lt;/code&gt;, you can open it, and you can edit it. But without the “Execute” permission, you can’t run the script.&lt;/p&gt;
&lt;h2&gt;
  
  
  Viewing Permissions
&lt;/h2&gt;

&lt;p&gt;Try something out for me: Open up a terminal, go to a directory with a bunch of files, and type &lt;code&gt;ls -l&lt;/code&gt;. This will list all the files in the directory (&lt;code&gt;ls&lt;/code&gt;) in a long format (&lt;code&gt;-l&lt;/code&gt;). You’ll get something like this:&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%2Fstevenwa.sh%2Fassets%2Fscreen-shot-2019-07-18-at-1.50.05-pm.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%2Fstevenwa.sh%2Fassets%2Fscreen-shot-2019-07-18-at-1.50.05-pm.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Look on the very left column, and you’ll see a combination of 10 &lt;code&gt;r&lt;/code&gt;’s, &lt;code&gt;w&lt;/code&gt;’s, &lt;code&gt;x&lt;/code&gt;’s, and &lt;code&gt;-&lt;/code&gt;‘s. This is not a random jumble of letters, but actually a lineup of permissions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The first digit is the directory flag. If the row describes a directory, it’ll be &lt;code&gt;d&lt;/code&gt;, otherwise it will be &lt;code&gt;-&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;The next three digits are the User permissions. This is set up in order &lt;code&gt;rwx&lt;/code&gt; or “Read, Write, E &lt;strong&gt;x&lt;/strong&gt; ecute.&lt;/li&gt;
&lt;li&gt;The next three are the Group permissions, set up the same as the User&lt;/li&gt;
&lt;li&gt;The next three are Other permissions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let’s take this line for example&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;-rw-r--r-- 1 stevewashington staff 805 Jul 17 19:11 package.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can take that first column, and break it up into 4 sections:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;-&lt;/code&gt; &amp;gt;&amp;gt; This is the directory flag. package.json is not a directory, so this is ’-’&lt;br&gt;&lt;br&gt;
&lt;code&gt;rw-&lt;/code&gt; &amp;gt;&amp;gt; these next three digits are the “User” section. So the Owner (“stevewashington”) can Read the file, Write to the file, but not Execute it.&lt;br&gt;&lt;br&gt;
&lt;code&gt;r--&lt;/code&gt; &amp;gt;&amp;gt; These are the “Group” permissions. Anyone in the defined Group (“staff”) can read the file, but not write to it or execute it.&lt;br&gt;&lt;br&gt;
&lt;code&gt;r--&lt;/code&gt; &amp;gt;&amp;gt; These are “Other” permissions, which are the same as “Group,” can read, but not write or execute.&lt;/p&gt;

&lt;h2&gt;
  
  
  Okay but what about the numbers?
&lt;/h2&gt;

&lt;p&gt;The number in the &lt;code&gt;chmod&lt;/code&gt; command (&lt;code&gt;755&lt;/code&gt; in the example above) are in “octal”, or base-8. Each digit can hold a number from 0-7, and the number 8 is “10” in octal.&lt;/p&gt;

&lt;p&gt;You may notice that the number has 3 digits. You may also see that there are three permissions roles, User, Group, and Other. Put these together, and you can read these as separate permission sets: User is 7, Group is 5, and Other is also 5.&lt;/p&gt;

&lt;p&gt;So now we just need to convert each digit from octal to a set of 3 letters: &lt;code&gt;rwx&lt;/code&gt;. And we will be using binary as an intermediary:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Octal/Decimal&lt;/th&gt;
&lt;th&gt;Binary&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;User&lt;/td&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;td&gt;111&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Group&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;101&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Other&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;101&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Here we have the conversions for each digit in &lt;code&gt;755&lt;/code&gt; to binary (as in “seven, five, five”, not “seven hundred fifty five”)&lt;/p&gt;

&lt;p&gt;Here’s another “coincidence”, the binary numbers also have 3 digits! So we can turn on or off “rwx” flags based on whether the binary number is 1 or 0:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Octal/Decimal&lt;/th&gt;
&lt;th&gt;Binary&lt;/th&gt;
&lt;th&gt;Permissions&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;User&lt;/td&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;td&gt;111&lt;/td&gt;
&lt;td&gt;rwx&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Group&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;101&lt;/td&gt;
&lt;td&gt;r-x&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Other&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;101&lt;/td&gt;
&lt;td&gt;r-x&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;If we mash them together, we see that &lt;code&gt;chmod 755 ./file.txt&lt;/code&gt; means:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Change &lt;code&gt;./file.txt&lt;/code&gt; so that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the owner can read, write, and execute it&lt;/li&gt;
&lt;li&gt;the defined group can read it and execute it&lt;/li&gt;
&lt;li&gt;everyone else can also read and execute it&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;p&gt;Knowing this, this is actually fairly open permissions for a file. Are you use you want absolutely everyone to be able to execute a program on your server? 🤔&lt;/p&gt;

&lt;p&gt;Using the &lt;code&gt;package.json&lt;/code&gt; example from above, we can work it out backwards:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Permissions&lt;/th&gt;
&lt;th&gt;Binary&lt;/th&gt;
&lt;th&gt;Octal/Decimal&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;User&lt;/td&gt;
&lt;td&gt;rw-&lt;/td&gt;
&lt;td&gt;110&lt;/td&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Group&lt;/td&gt;
&lt;td&gt;r—&lt;/td&gt;
&lt;td&gt;100&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Other&lt;/td&gt;
&lt;td&gt;r—&lt;/td&gt;
&lt;td&gt;100&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;So copying the permissions of &lt;code&gt;package.json&lt;/code&gt; we’d use something like &lt;code&gt;chmod 644 ./file.txt&lt;/code&gt;. This means for package.json:&lt;/p&gt;

&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;the owner can read, write, but not execute it&lt;/li&gt;
&lt;li&gt;the defined group can only read it&lt;/li&gt;
&lt;li&gt;everyone else can only read it as well&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;p&gt;Which makes sense! You can’t really “execute” .json files, so there’s no reason to give that permission to anyone.&lt;/p&gt;

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

&lt;p&gt;This was a basic overview of Unix(-like) permissions and how to understand them. Now you know what &lt;code&gt;chmod 755 ./file.sh&lt;/code&gt; means, and can make smart decisions to fix your issue. This is a crucial part (and only a part!) in keeping your files and server safe.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Photo by Alex Martinez on Unsplash&lt;/em&gt;&lt;/p&gt;

</description>
      <category>unix</category>
      <category>permissions</category>
      <category>serveradmin</category>
    </item>
    <item>
      <title>DemandPad</title>
      <dc:creator>Steven Washington</dc:creator>
      <pubDate>Wed, 22 May 2019 22:01:49 +0000</pubDate>
      <link>https://forem.com/washingtonsteven/demandpad-3mal</link>
      <guid>https://forem.com/washingtonsteven/demandpad-3mal</guid>
      <description>&lt;h2&gt;
  
  
  Basic Info
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://relaxed-torvalds-97ac55.netlify.com/" rel="noopener noreferrer"&gt;Link to Application&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/washingtonsteven/demandpad" rel="noopener noreferrer"&gt;Github Repo&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Goal
&lt;/h2&gt;

&lt;p&gt;This was a personal project with a personal goal: have a quick utility to open up and take notes.&lt;/p&gt;

&lt;p&gt;In the past, I would have a bookmark to open a url: &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fu03jrdnmfmsjtugajiff.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fu03jrdnmfmsjtugajiff.png" alt="browser screenshot of using a data uri to create a makeshift notepad"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Try it!* It will open up a blank webpage that you can type in. This is great for jotting down quick notes (just like a post it note), with almost no system overhead, having to open a separate program, having to find a pen, etc.&lt;/p&gt;

&lt;p&gt;&lt;small&gt;* &lt;em&gt;Type the URL from the screenshot, unfortunately I can't type such a data URI into the body of this post. Check out &lt;a href="https://github.com/thepracticaldev/dev.to/issues/2924"&gt;this issue on Github&lt;/a&gt;, seems to be an issue to prevent XSS.&lt;/em&gt;&lt;/small&gt;&lt;/p&gt;

&lt;p&gt;However, this approach has one major shortfall, saving. Once you close the tab, the notes are gone forever, akin to tossing the post-it note. Sometimes I would leave this tab open for days, only to despair when I accidentally closed it, or an overeager update would restart my computer.&lt;br&gt;
My solution is to make a webapp that is nearly as light as the dataURI, but with the ability to save and load previous notes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Saving/Loading mechanism
&lt;/h2&gt;

&lt;p&gt;Notes are saved/loaded from the browser's &lt;code&gt;localStorage&lt;/code&gt;. The mechanism saves on every keypress, serializing all the note data into a JSON string and saving it into the local store (which can only save strings).&lt;/p&gt;

&lt;p&gt;One big limitation of this is the fact that notes don't "travel" with me, so any new device I use will have its own set of notes. This also applies to separate profiles (at least in Chrome) on the same machine. I use separate profiles for my personal (Google) and work (GApps) accounts. This means that the notes don't "cross-pollinate," for better or for worse.&lt;/p&gt;

&lt;h2&gt;
  
  
  Deleting Notes
&lt;/h2&gt;

&lt;p&gt;Deleting all notes is fairly easy, it is simply a matter of setting the localStorage key to an empty string. Easy.&lt;/p&gt;

&lt;p&gt;It's a bit more complicated to delete a single note, which involves messing with an array, removing an item and ensuring the rest of the items are still ordered properly.&lt;/p&gt;

&lt;p&gt;Another issue with deleting single notes is making sure that the user really &lt;em&gt;wants&lt;/em&gt; to delete it. This is usually handled by some sort of confirmation message. &lt;a href="https://twitter.com/esaevian/status/975218196755173377" rel="noopener noreferrer"&gt;I have a similar mechanism working on ReactVN&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This time, I wanted to try something a little different, inspired by a game that I was deep in at the time: &lt;em&gt;Destiny 2&lt;/em&gt;. In that game, you can delete items from your inventory by holding a button. At that point a bar begins to fill up. If you release the button the bar resets, but if you hold the button until the bar fills, the item is removed. This is sort of a fun interactive way to confirm the user wants to delete the item without extra dialongs and extra mouse motion.&lt;/p&gt;

&lt;p&gt;(They also give priority to various items by changing the color of the bar and how long it takes to delete something! I could go more into it, but maybe for another time).&lt;/p&gt;

&lt;p&gt;Basically, I liked this interaction for confirming deletion, and reimplemented it in React, using &lt;code&gt;setTimeout&lt;/code&gt; and &lt;code&gt;state&lt;/code&gt; to update a value which drove the CSS property &lt;code&gt;width&lt;/code&gt;. For performance reasons, it may have been better to use &lt;code&gt;transform:scale(x)&lt;/code&gt; instead of &lt;code&gt;width&lt;/code&gt;, since &lt;code&gt;width&lt;/code&gt; causing the browser to re-layout which hurts performance and frame rate. &lt;a href="https://github.com/washingtonsteven/demandpad/issues/16" rel="noopener noreferrer"&gt;Got an issue for that now.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/washingtonsteven/demandpad/blob/master/src/NoteList.js#L11" rel="noopener noreferrer"&gt;You can see the underlying code for the DeleteButton component here&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Process
&lt;/h2&gt;

&lt;p&gt;This personal project I tried to implement a Git workflow of always creating feature updates on a separate branch, and making a pull request to bring the updated and tested change into &lt;code&gt;master&lt;/code&gt;. This was great to get in the habit of this sort of flow. It's also cool to go through Github and see the issue/commit/pull request history and see where certain changes happened at a glance. I still like doing git actions via the command line, especially to truly understand what's happening, but using Github in this way has been a great way to explore all the integration features the service has.&lt;/p&gt;

&lt;p&gt;In addition, Netlify will take note of pull request, automatically building them in a Deploy Preview. This made it really nice to test out changes in the live environment as the local server from &lt;code&gt;create-react-app&lt;/code&gt; isn't always the same.&lt;/p&gt;

&lt;h2&gt;
  
  
  Underlying Tech
&lt;/h2&gt;

&lt;p&gt;DemandPad is built in React. Everything is client side, using built in browser APIs. Hopefully one day I will update this to use a 3rd party auth service (Netlify Identity, anyone?) which will also allow the notes to be saved in the cloud, to avoid the saving issue mentioned above.&lt;/p&gt;

&lt;p&gt;Hosted on Netlify, which has been my go-to lately for putting a front-end project online.&lt;/p&gt;

&lt;h2&gt;
  
  
  Screenshots
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F4hjt2qsz82bqf35xrigg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F4hjt2qsz82bqf35xrigg.png" alt="Dempandpad screenshot 1 - Showing the sidebar in the midst of deleting an item"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F5jusicy4squjbeb70bdt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F5jusicy4squjbeb70bdt.png" alt="Demandpad screenshot 2 - Showing the editing area full of markdown syntax-highlighted text"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>react</category>
      <category>utility</category>
      <category>showdev</category>
    </item>
    <item>
      <title>My Development Graveyard, Part 1</title>
      <dc:creator>Steven Washington</dc:creator>
      <pubDate>Tue, 14 Aug 2018 00:00:00 +0000</pubDate>
      <link>https://forem.com/washingtonsteven/my-development-graveyard-part-1-3obc</link>
      <guid>https://forem.com/washingtonsteven/my-development-graveyard-part-1-3obc</guid>
      <description>&lt;p&gt;The concept of a Github Graveyard was started by Isaac Lyman in &lt;a href="https://dev.to/isaacandsuch/github-graveyards-ill-show-you-mine-49lh"&gt;this dev.to post&lt;/a&gt;. The idea is to go through all your old projects that you never touch anymore and remember where you’ve come from to help you get to where you’re going. I loved the idea immediately, and decided to start my own!&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://github.com/washingtonsteven/aterriblefate"&gt;aterriblefate&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Background:&lt;/strong&gt; This is a simple, single page site, mostly to test out how Github Pages worked. I got the idea on New Year’s 2018, to create a countdown to the next year that looks like the “x days remain” cards from the Legend of Zelda: Majora’s Mask.&lt;/p&gt;

&lt;p&gt;&lt;a href="///static/zelda-dc906193c8804853019bc397fc94300f-5979c.jpg"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--eAGVTsD2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://stevenwa.sh/static/zelda-dc906193c8804853019bc397fc94300f-5979c.jpg" alt="The Legend of Zelda: Majora's Mask - Dawn of the First Day"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What I Learned&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Working with Javascript dates&lt;/li&gt;
&lt;li&gt;Additional Practice matching styles&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Why it died:&lt;/strong&gt; This is actually alive at &lt;a href="http://aterriblefate.net"&gt;http://aterriblefate.net&lt;/a&gt;. There are bugs that have popped up (mostly due to spacing and text sizing) since testing with the date Jan 1 2018 yielded limited results. This was never a serious project, so my attention was grabbed away from this pretty quickly.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://github.com/washingtonsteven/washingtonsteven.github.io"&gt;washingtonsteven.github.io&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Background:&lt;/strong&gt; An older version of my personal site, built with Jekyll for hosting on Github Pages (now I’m using Gatsby and hosting on Netlify).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What I Learned&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;First step into static site generators, using Jekyll&lt;/li&gt;
&lt;li&gt;Github Pages / Domain management&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Why it died:&lt;/strong&gt; I didn’t like the design I came up with, mainly. This was also just after I dove headfirst into react, and was itching to try more react-based projects (such at Gatsby!).&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://github.com/washingtonsteven/react-json-component"&gt;react-json-component&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Background:&lt;/strong&gt; As I was learning more about React, I came across some situations where JSX just wouldn’t cut it. In this case I dug into &lt;code&gt;React.createElement&lt;/code&gt; directly to create my components. I eventually wrote some login to take some specially formatted JSON, and spit out actual React Components.&lt;/p&gt;

&lt;p&gt;The next step was to create a library that cleanly does this for you, rather than the logic I wrote that was wrapped up in other, application specfici logic&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What I Learned&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Deeper dive into React component creation&lt;/li&gt;
&lt;li&gt;Incidentally, I also dove into what is necessary to create and publish a React Component on npm (even though this one was never published). In addition, taking considerations to keep the component generic enough to fit a wide array of situations that people will throw at it.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Why it died:&lt;/strong&gt; It had mostly run its course, really. This was more of an exercise in React rather than a final living, breathing project. Rest in Peace.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://github.com/washingtonsteven/genmo"&gt;genmo&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Background:&lt;/strong&gt; Before &lt;a href="http://stevenwa.sh/project/react-vn"&gt;ReactVN was a thing&lt;/a&gt;, my first foray into text adventures was a little command line tool. My eventual plan was to have this become a simulation which can generate a series of actions in a fictional world and generate a short story for submission to &lt;a href="https://nanogenmo.github.io/"&gt;NaNoGenMo, National Novel Generating Month&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What I Learned&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;This was my first look into building command line tools and a deep dive into node system calls&lt;/li&gt;
&lt;li&gt;I also built out genmo as an API to be integrated into any sort of app, and in fact included a call-and-response type adventure into a Slack bot.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Why it died:&lt;/strong&gt; I would love to clean this up one day, but a lot of the logic did end up being sort of “spaghetti” by the end of it, fixing and patching bug after bug instead of thinking of the problem holistically. At this point updates and fixes would be incredibly cumbersome and locked to original design ideas. Next step here would be to do massive refactor, to the point of a possible rewrite.&lt;/p&gt;




&lt;p&gt;That’s it for part 1! Like many I have a bunch of projects in my past to look over, so look forward to the next one!&lt;/p&gt;

</description>
      <category>graveyard</category>
    </item>
    <item>
      <title>React's new Context API and Actions</title>
      <dc:creator>Steven Washington</dc:creator>
      <pubDate>Sat, 31 Mar 2018 11:19:41 +0000</pubDate>
      <link>https://forem.com/washingtonsteven/reacts-new-context-api-and-actions-446o</link>
      <guid>https://forem.com/washingtonsteven/reacts-new-context-api-and-actions-446o</guid>
      <description>&lt;p&gt;&lt;em&gt;Photo:&lt;/em&gt; &lt;a href="https://unsplash.com/@danielwatsondesign?utm_medium=referral&amp;amp;utm_campaign=photographer-credit&amp;amp;utm_content=creditBadge" rel="noopener noreferrer" title="Download free do whatever you want high-resolution photos from Daniel Watson"&gt;Daniel Watson&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Edit: 4/2/2018 - &lt;a href="https://dev.to/dan_abramov/comment/2nga"&gt;It was pointed out to me&lt;/a&gt; that the example in this post had a performance issue, where &lt;code&gt;render&lt;/code&gt; was called on Consumers unnecessarily. I've updated the article, examples, and the CodeSandbox to rectify this.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The new React Context API (&lt;del&gt;coming soon&lt;/del&gt; now here! in React 16.3) is a massive update of the old concept of context in React, which allowed components to share data outside of the parent &amp;gt; child relationship.  There are many examples and tutorials out there that show how to read from the state provided by context, but you can also pass functions that modify that state so consumers can respond to user interactions with state updates!&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Context?
&lt;/h2&gt;

&lt;p&gt;The context API is a solution to help with a number of problems that come with a complex state that is meant to be shared with many components in an app:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; It provides a single source of truth for data that can be directly accessed by components that are interested, which means:&lt;/li&gt;
&lt;li&gt; It avoids the "prop-drilling" problem, where components receive data only to pass it on to their children, making it hard to reason about where changes to state are (or aren't) happening.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  B-but Redux!
&lt;/h3&gt;

&lt;p&gt;Redux is a fantastic tool that solves these problems as well. However Redux also brings a lot of other features to the table (mostly around enforcement of the purity of state and reducers) along with required boilerplate that may be cumbersome depending on what is needed. For perspective, Redux uses the (old) context API.&lt;/p&gt;

&lt;p&gt;Check out this article by Dan the Man himself: &lt;a href="https://medium.com/@dan_abramov/you-might-not-need-redux-be46360cf367"&gt;You Might Not Need Redux&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What's Context do?
&lt;/h2&gt;

&lt;p&gt;There are plenty of articles on this (&lt;a href="https://medium.com/dailyjs/reacts-%EF%B8%8F-new-context-api-70c9fe01596b"&gt;I particularly like this one&lt;/a&gt;), so I don't want to go into too many details about how this works. You've seen the examples so far, and they're mostly missing something: &lt;em&gt;how to update the state in the provider.&lt;/em&gt; That state is sitting there, and everyone can read it, but how do we writeto it?&lt;/p&gt;

&lt;h2&gt;
  
  
  Simple Context Example
&lt;/h2&gt;

&lt;p&gt;In many of these examples we make a custom provider to wrap around React's, which has its own state that is passed in as the &lt;code&gt;value&lt;/code&gt;. Like so:&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;context.js&lt;/code&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Context&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createContext&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;DuckifyProvider&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Component&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;isADuck&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;render&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;children&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; 
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Provider&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/Context.Provider&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;DuckifyConsumer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Consumer&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Seems simple, enough. Now we can use the &lt;code&gt;DuckifyConsumer&lt;/code&gt; to read that state:&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;DuckDeterminer.js&lt;/code&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;DuckifyConsumer&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./context&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;DuckDeterminer&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Component&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;render&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;DuckifyConsumer&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;isADuck&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;isADuck&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;quack&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;...silence...&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;          &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;        &lt;span class="p"&gt;)}&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/DuckifyConsumer&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;DuckDeterminer&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Passing Functions
&lt;/h2&gt;

&lt;p&gt;Now, what if we wanted to emulate a witch turning something into a duck (stay with me here)? We need to set &lt;code&gt;isADuck&lt;/code&gt; to &lt;code&gt;true&lt;/code&gt;, but how?&lt;/p&gt;

&lt;p&gt;We pass a function.&lt;/p&gt;

&lt;p&gt;In Javascript, functions are known as "first-class", meaning we can treat them as objects, and pass them around, even in state and in the Provider's &lt;code&gt;value&lt;/code&gt; prop. It wouldn't surprise me if the reason why the maintainers chose &lt;code&gt;value&lt;/code&gt; and not &lt;code&gt;state&lt;/code&gt; for that prop is to allow this separation of concepts. &lt;code&gt;value&lt;/code&gt; can be anything, though likely based on &lt;code&gt;state&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In this case, we can add an &lt;code&gt;dispatch&lt;/code&gt; function to the &lt;code&gt;DuckifyProvider&lt;/code&gt; state. &lt;code&gt;dispatch&lt;/code&gt; will take in an action (defined as a simple object), and call a reducer function (see below) to update the Provider's state (&lt;em&gt;I saw this method of implementing a redux-like reducer without redux somewhere, but I'm not sure where. If you know where, let me know so I can properly credit the source!&lt;/em&gt;).&lt;/p&gt;

&lt;p&gt;We pass the &lt;code&gt;state&lt;/code&gt; into the &lt;code&gt;value&lt;/code&gt; for the Provider, so the consumer will have access to that &lt;code&gt;dispatch&lt;/code&gt; function as well.&lt;/p&gt;

&lt;p&gt;Here's how that can look:&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;context.js&lt;/code&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Context&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createContext&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;reducer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;TOGGLE&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;isADuck&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isADuck&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;DuckifyProvider&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Component&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;isADuck&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;dispatch&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;action&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;reducer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="nx"&gt;render&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;props&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;children&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Provider&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/Context.Provider&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;;
&lt;/span&gt;  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;DuckifyConsumer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Consumer&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note that we have &lt;code&gt;dispatch&lt;/code&gt; in our state, which we pass into &lt;code&gt;value&lt;/code&gt;. This is due to a &lt;a href="https://reactjs.org/docs/context.html#caveats"&gt;caveat in how the need to re-render a consumer is determined&lt;/a&gt; (&lt;a href="https://dev.to/dan_abramov/comment/2nga"&gt;Thanks, Dan for pointing that out!&lt;/a&gt;). As long as the reference to &lt;code&gt;this.state&lt;/code&gt; stays pointed to the same object, any updates the make the Provider re-render, but don't actually change the Provider's state, won't trigger re-renders in the consumers.&lt;/p&gt;

&lt;p&gt;Now, in &lt;code&gt;DuckDeterminer&lt;/code&gt;, we can create an action (&lt;code&gt;{type:"TOGGLE"}&lt;/code&gt;) that is dispatched in the &lt;code&gt;button&lt;/code&gt;'s &lt;code&gt;onClick&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;(We can also enforce certain action types with an enum object that we export for the &lt;code&gt;DuckifyContext&lt;/code&gt; file. You'll see this when you check out the &lt;a href="https://codesandbox.io/s/kw25vnv25v"&gt;CodeSandbox&lt;/a&gt; for this)&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;DuckDeterminer.js&lt;/code&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;DuckifyConsumer&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./DuckContext&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;DuckDeterminer&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Component&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;render&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;DuckifyConsumer&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;isADuck&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;dispatch&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
              &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;isADuck&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;🦆 quack&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;...silence...&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;              &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;TOGGLE&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;})}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="nx"&gt;Change&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;
              &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;          &lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}}&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/DuckifyConsumer&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;DuckDeterminer&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The secret sauce here is the &lt;code&gt;dispatch&lt;/code&gt; function. Since we can pass it around like any other object, we can pass it into our render prop function, and call it there! At that point the state of our Context store is updated, and the view inside the Consumer updates, toggling on and off whether the duck truly exists.&lt;/p&gt;

&lt;h3&gt;
  
  
  Extra credit
&lt;/h3&gt;

&lt;p&gt;You can (read: I like to) also add a &lt;code&gt;helpers&lt;/code&gt; field alongside &lt;code&gt;state&lt;/code&gt; and &lt;code&gt;dispatch&lt;/code&gt;, as a set of functions that "help" you sift through the data. If &lt;code&gt;state&lt;/code&gt; is a massive array, perhaps you can write a &lt;code&gt;getLargest&lt;/code&gt; or &lt;code&gt;getSmallest&lt;/code&gt; or &lt;code&gt;getById&lt;/code&gt; function to help you traverse the list without having to split the implementation details of accessing various items in a list in your consumer components.&lt;/p&gt;

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

&lt;p&gt;Used responsibly, the new Context API can be very powerful, and will only grow as more and more awesome patterns are discovered. But every new pattern (including this one, even) should be used with care and knowledge of the tradeoffs/benefits, else you're dipping your toes in deaded &lt;em&gt;antipattern&lt;/em&gt; territory.&lt;/p&gt;

&lt;p&gt;React's new context API, is incredibly flexible in what you can pass through it. Typically you will want to pass your state into the &lt;code&gt;value&lt;/code&gt; prop to be available to consumers, but passing along functions to modify state is possible as well, and can make interacting with the new API a breeze.&lt;/p&gt;

&lt;h3&gt;
  
  
  Try it out
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;DuckDeterminer&lt;/code&gt; component is available to play with on &lt;a href="https://codesandbox.io/s/kw25vnv25v"&gt;CodeSandbox, right now!&lt;/a&gt;&lt;/p&gt;

</description>
      <category>react</category>
      <category>javascript</category>
    </item>
    <item>
      <title>ReactVN</title>
      <dc:creator>Steven Washington</dc:creator>
      <pubDate>Mon, 12 Mar 2018 00:00:00 +0000</pubDate>
      <link>https://forem.com/washingtonsteven/reactvn-124b</link>
      <guid>https://forem.com/washingtonsteven/reactvn-124b</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--2VboWAGB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://stevenwa.sh/static/featured_alpha_20180325-12b62c745e507a65ad151afab244d53d.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--2VboWAGB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://stevenwa.sh/static/featured_alpha_20180325-12b62c745e507a65ad151afab244d53d.gif" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;React VN is a Visual Novel Editor and Player for playing and writing text adventures.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;NB: this is an older project that I had sitting in my drafts for a while. This has been live on &lt;a href="https://stevenwa.sh/project/react-vn"&gt;my site&lt;/a&gt; for a while, so no time like the present to publish here! Some statements in here are a bit...dated...however.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Technology
&lt;/h2&gt;

&lt;h3&gt;
  
  
  React
&lt;/h3&gt;

&lt;p&gt;React VN was written for the web with Javascript, using React as a framework for the data and managing interactions.&lt;/p&gt;

&lt;h3&gt;
  
  
  create-react-app
&lt;/h3&gt;

&lt;p&gt;The React setup was scaffolded with &lt;a href="https://github.com/facebook/create-react-app"&gt;Create React App&lt;/a&gt;, and then was ejected for a few reasons:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Adding Sass compilation (using &lt;code&gt;sass-loader&lt;/code&gt;) - Faciliating a special build that only builds the Player (default build includes the Editor)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  React 16.3 Context API
&lt;/h3&gt;

&lt;p&gt;This project also makes used of the new (and unreleased, at the time) React Context API. The Context is set up in &lt;code&gt;src/data/StoryContext.js&lt;/code&gt;. In that file there is a &lt;code&gt;StoryProvider&lt;/code&gt; that wraps around the default Context.Provider component that providers the story data to the consumer. However it also exposes several functions that serve as an API for the &lt;code&gt;storyData&lt;/code&gt;: helper functions (for quick access for nodes) and actions (for modifying nodes).&lt;/p&gt;

&lt;h2&gt;
  
  
  Deployment
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Concept
&lt;/h3&gt;

&lt;p&gt;The application is split up into two separate deployments, an “editor” build and a “player” build. The Editor includes tools to create a new story, edit an existing one, and export a story to a .json file. The Editor also automatically turns on “debug mode” where you can see a bit of what’s happening under the hood as the story is being processed. The Player can only load and play .json stories.&lt;/p&gt;

&lt;h3&gt;
  
  
  Processes
&lt;/h3&gt;

&lt;p&gt;The initial deployment plan is to host both web apps, and allow people to share .json files as they wished (created in the editor webapp). A person would receive someone else’s .json and upload it to the Player webapp to play the story.&lt;/p&gt;

&lt;p&gt;Soon, an officially supported deployment will be to allow editors to download the source for the app, and run their own editor apps on their local machines or even self-host, and do the same for their player apps. In this case the Player can be set to load a specific .json file instead of asking for a specific screen to load.&lt;/p&gt;

&lt;h3&gt;
  
  
  Current State
&lt;/h3&gt;

&lt;p&gt;Currently, both apps are deployed via Github to Netlify (&lt;a href="http://react-vn.netlify.com"&gt;Editor&lt;/a&gt; and &lt;a href="http://react-vn-player.netlify.com"&gt;Player&lt;/a&gt;). Each build is also run through TravisCI to run tests, and on tagged releases, will generate a &lt;code&gt;player.zip&lt;/code&gt; that contains all the files needed to host a Player app which will be attached to the Github release.&lt;/p&gt;

&lt;h2&gt;
  
  
  Links
&lt;/h2&gt;

&lt;p&gt;Source: &lt;a href="https://github.com/washingtonsteven/react-vn"&gt;https://github.com/washingtonsteven/react-vn&lt;/a&gt;&lt;br&gt;&lt;br&gt;
Editor: &lt;a href="http://react-vn.netlify.com"&gt;http://react-vn.netlify.com&lt;/a&gt;&lt;br&gt;&lt;br&gt;
Player: &lt;a href="http://react-vn-player.netlify.com"&gt;http://react-vn-player.netlify.com&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Screenshots
&lt;/h2&gt;

&lt;p&gt;&lt;a href="///static/screenshot01-89b755b63dbe2db5956d39a571d01197-a5f62.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--bMv68tYD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://stevenwa.sh/static/screenshot01-89b755b63dbe2db5956d39a571d01197-fb8a0.png" alt="screenshot01"&gt;&lt;/a&gt;&lt;a href="///static/screenshot02-045ed90c2b510c65f9dfb731f94c6865-73fc3.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s---6Vr2M5G--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://stevenwa.sh/static/screenshot02-045ed90c2b510c65f9dfb731f94c6865-fb8a0.png" alt="screenshot02"&gt;&lt;/a&gt;&lt;a href="///static/screenshot03-fde671570e6f62c27055562d9c6c1597-27903.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--zlE4j6dH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://stevenwa.sh/static/screenshot03-fde671570e6f62c27055562d9c6c1597-fb8a0.png" alt="screenshot03"&gt;&lt;/a&gt;&lt;a href="///static/screenshot04-3b871aa51e4ee0cb1682e78476cf49bb-415b9.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--RstLgV-X--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://stevenwa.sh/static/screenshot04-3b871aa51e4ee0cb1682e78476cf49bb-fb8a0.png" alt="screenshot04"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>react</category>
      <category>writing</category>
    </item>
    <item>
      <title>Caching Component data in React</title>
      <dc:creator>Steven Washington</dc:creator>
      <pubDate>Sun, 04 Mar 2018 16:47:26 +0000</pubDate>
      <link>https://forem.com/washingtonsteven/caching-component-data-in-react--4m85</link>
      <guid>https://forem.com/washingtonsteven/caching-component-data-in-react--4m85</guid>
      <description>&lt;h2&gt;
  
  
  The Problem
&lt;/h2&gt;

&lt;p&gt;So I recently came across an issue in a &lt;a href="https://github.com/washingtonsteven/react-vn" rel="noopener noreferrer"&gt;React App&lt;/a&gt; that I'm building (for funsies):&lt;/p&gt;

&lt;p&gt;I have an array of objects, that potentially can get huge. Each one of those objects has an &lt;code&gt;id&lt;/code&gt;, so implementing &lt;code&gt;Array.find&lt;/code&gt; to get the item I want should work.&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;nodes&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;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;abc&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Lorem ipsum&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;def&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Dolor sit&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getNode&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;nodes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="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="nf"&gt;getNode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;abc&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="c1"&gt;// =&amp;gt; { id:"abc", content:"Lorem ipsum" }&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;However, when &lt;code&gt;nodes&lt;/code&gt; gets big, &lt;code&gt;Array.find&lt;/code&gt; is going to be iterating over &lt;em&gt;each item&lt;/em&gt;, which can get expensive. So we can implement a 'cache' of sorts to help out.&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;nodes&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;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;abc&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Lorem ipsum&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;def&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Dolor sit&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;keyedNodes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getNode&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;id&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="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;keyedNodes&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;keyedNodes&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;nodes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;keyedNodes&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;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="nf"&gt;getNode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;abc&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="c1"&gt;// =&amp;gt; { id:"abc", content:"Lorem ipsum" }&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="nf"&gt;getNode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;abc&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="c1"&gt;// This time we are coming from keyedNodes!&lt;/span&gt;
&lt;span class="c1"&gt;// =&amp;gt; { id:"abc", content:"Lorem ipsum" }&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Seems simple enough!&lt;/p&gt;

&lt;h2&gt;
  
  
  React and data
&lt;/h2&gt;

&lt;p&gt;Being a relative React newbie, I had it drilled into my head where the sources of data in an app should be: either &lt;code&gt;prop&lt;/code&gt; or &lt;code&gt;state&lt;/code&gt;. &lt;code&gt;props&lt;/code&gt; holds data that the component receives (and it shouldn't update itself), and &lt;code&gt;state&lt;/code&gt; holds the current state of the component, which that same component has complete control over (via &lt;code&gt;setState&lt;/code&gt; of course!).&lt;/p&gt;

&lt;p&gt;Armed with this info, I went to implement this memoization tactic using the component's state, and it got super messy given &lt;code&gt;setState&lt;/code&gt;'s asynchronous nature.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://codesandbox.io/s/jvpz0qxr55" rel="noopener noreferrer"&gt;Check out the demo on CodeSandbox&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://codesandbox.io/s/jvpz0qxr55" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcodesandbox.io%2Fstatic%2Fimg%2Fplay-codesandbox.svg" alt="Edit Memoize Component Data in state"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Look at that nasty &lt;code&gt;getNode&lt;/code&gt; function! We have to wait for the state to resolve before actually changing the node, or else we risk overwriting the state at the wrong time. (the state in &lt;code&gt;changeNodes&lt;/code&gt;, which doesn't have the &lt;code&gt;keyedNodes&lt;/code&gt; update in &lt;code&gt;getNode&lt;/code&gt;, would overwrite the &lt;code&gt;keyedNodes&lt;/code&gt; object to be blank! No help at all!).&lt;/p&gt;

&lt;p&gt;I lived with this for a while, then I looked over at &lt;a href="https://egghead.io/lessons/egghead-use-class-components-with-react" rel="noopener noreferrer"&gt;Kent Dodd's video on using class fields&lt;/a&gt; (which is useful for getting around those pesky &lt;code&gt;bind&lt;/code&gt; calls). This reminded me that class fields exist (&lt;a href="https://github.com/tc39/proposal-class-fields" rel="noopener noreferrer"&gt;sort of...&lt;/a&gt;, the default babel config for &lt;a href="https://github.com/facebook/create-react-app" rel="noopener noreferrer"&gt;Create React App&lt;/a&gt; does allow for their use). So not only could I put &lt;code&gt;state&lt;/code&gt; in as a class field (along with arrow functions to create properly bound functions for component callbacks), but anything else can go here too!&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Note: You don't actually need to use class fields for this, either! &lt;code&gt;this.keyedNodes&lt;/code&gt; in &lt;code&gt;constructor&lt;/code&gt; will do the same thing.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;So, putting &lt;code&gt;keyedNodes&lt;/code&gt; on a classVariable renders something similar, but much easier to read:&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://codesandbox.io/s/44m6073m0" rel="noopener noreferrer"&gt;Check out the demo on CodeSandbox&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://codesandbox.io/s/44m6073m0" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcodesandbox.io%2Fstatic%2Fimg%2Fplay-codesandbox.svg" alt="Edit Memoize Component Data in a class field!"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Downsides?
&lt;/h2&gt;

&lt;p&gt;The main downside to this is that React doesn't look at class fields other than &lt;code&gt;state&lt;/code&gt; and &lt;code&gt;props&lt;/code&gt; to control the rendering of updates. So if for whatever reason you need this cache to be tied to the render loop, you are stuck with the first way: keeping the cache in state. &lt;/p&gt;

&lt;p&gt;I believe that in most cases, however, the cache doesn't need to trigger or get updated by React itself. The cache should follow any updates to the component, not preempt them. &lt;/p&gt;

&lt;p&gt;To that end, perhaps we can an addition in &lt;code&gt;componentDidUpdate&lt;/code&gt; to clear the cache if &lt;code&gt;this.state.nodes&lt;/code&gt; just went through an update, so we aren't potentially dealing with old data. But this goes to show that data in class fields needs to be treated with care.&lt;/p&gt;

&lt;p&gt;One other side effect is that these class fields are bound to the &lt;em&gt;instance&lt;/em&gt; and not the &lt;em&gt;prototype&lt;/em&gt;. Meaning that another component on the page that is using the same set of data has to build its own cache, and can't borrow it. This can be fixed by putting the cache in state, lifting the cache to a parent component, or using a render prop (or HOC) with a &lt;code&gt;Cache&lt;/code&gt; component (or &lt;code&gt;withCache&lt;/code&gt; HOC).&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion - Use with caution!
&lt;/h2&gt;

&lt;p&gt;Holding on to component-specific (and even instance-specific) data within a class or object field can be very useful for some quick optimizations, or just holding some data that doesn't necessarily need to be ensnared in the React render loop, where the async nature of &lt;code&gt;setState&lt;/code&gt; can cause strange problems and race conditions that can lead to less-than-readable code. &lt;strong&gt;However&lt;/strong&gt;, because the class field is outside of the render loop, updates to that data won't be managed by React, and can cause problems along the way if used improperly. A simple cache for storing data that needs to be readily accessible is a great use for this, as a cache naturally falls back onto the React state for a miss, and should 'follow the leader' in taking the source of truth from state.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>react</category>
      <category>cache</category>
    </item>
    <item>
      <title>Yelling at Silicon (Part 1)</title>
      <dc:creator>Steven Washington</dc:creator>
      <pubDate>Tue, 13 Feb 2018 15:07:57 +0000</pubDate>
      <link>https://forem.com/washingtonsteven/yelling-at-silicon-part-1-2eef</link>
      <guid>https://forem.com/washingtonsteven/yelling-at-silicon-part-1-2eef</guid>
      <description>&lt;p&gt;The use of various voice-activated home assistants in everyday life has been booming lately. It started off with Siri, and Google followed with their Assistant. Alexa came on the scene and even Cortana has given it a go.&lt;/p&gt;

&lt;p&gt;These assistants come with a good set of features and functions that help you automate your life: setting timers, playing music, turning on and off lights, setting thermostats, etc. It's all very helpful! However, regardless of how many functions exist, there's never going to be a one-size-fits-all solution.&lt;/p&gt;

&lt;p&gt;So it's time to make one.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Play along by following what I have so far in &lt;a href="https://github.com/washingtonsteven/thorndike"&gt;Github&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  A bus tracking app
&lt;/h2&gt;

&lt;p&gt;My typical morning involves the usual things: waking up, checking Twitter while laying in bed for 20 minutes, rushing through breakfast/shower/dressing myself to get out the door on time. A part of this involves halting the whole process as I fiddle with my phone to bring up predictions from a bus tracking app (&lt;a href="https://nextbus.com"&gt;Nextbus&lt;/a&gt; in this case). It would be so much easier if I could instead ask my phone (or Google Home) for the latest buses by my house as I'm toasting a bagel or tying my shoes.&lt;/p&gt;

&lt;p&gt;To start, I built a quick function that interfaces with Nextbus' API. It accepts a stop name, and returns an object that has the prediction data that I need:&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;// Nextbus needs a stopId to look up predictions&lt;/span&gt;
&lt;span class="c1"&gt;// We have an object that maps stopNames to stopIds&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;stops&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;harvard&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;55555&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
  &lt;span class="c1"&gt;// other stops here...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;exports&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getPredictions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;stopName&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;stopId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;stops&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;stopName&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;nextbusURL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`http://webservices.nextbus.com/service/publicXMLFeed?command=predictions&amp;amp;a=mbta&amp;amp;stopId=&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;stopId&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="c1"&gt;// The Nextbus API is an XML api, so we use the xml2js package&lt;/span&gt;
  &lt;span class="c1"&gt;// to convert that to JSON&lt;/span&gt;
  &lt;span class="c1"&gt;// Then we have a parseSchedule function to clean up that&lt;/span&gt;
  &lt;span class="c1"&gt;// JSON, only returning the results we want&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;nextbusURL&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;xml&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;xml2js&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;xml&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;parseSchedule&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;parseSchedule&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;json&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;cleanedUp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;

  &lt;span class="c1"&gt;// Take `json` and extract only the info we care about&lt;/span&gt;
  &lt;span class="c1"&gt;// In the end, cleanedUp will be a multidimensional array of sentences, like:&lt;/span&gt;
  &lt;span class="c1"&gt;// [&lt;/span&gt;
  &lt;span class="c1"&gt;//   ['The next 77 to Arlington Heights at Harvard is arriving in 5 minutes'],&lt;/span&gt;
  &lt;span class="c1"&gt;//   ['The next 96 to Medford Square at Harvard is arriving in 8 minutes']&lt;/span&gt;
  &lt;span class="c1"&gt;// ]&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;cleanedUp&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;em&gt;If you're following in the &lt;a href="https://github.com/washingtonsteven/thorndike"&gt;Github repo&lt;/a&gt;, you'll notice that I'm only getting the first prediction for each route/direction combo. Shuffling around this function a bit and we can get multiple sets of predictions per route, which we can append to the inner array&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Making sentences - &lt;code&gt;filter&lt;/code&gt; and &lt;code&gt;join&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Before we can send this data to any voice assistant, we need to make actual, speakable sentences. &lt;/p&gt;

&lt;p&gt;The &lt;code&gt;cleanedUp&lt;/code&gt; object from &lt;code&gt;parseSchedule&lt;/code&gt; is a multi-dimensional array. The first dimension is a set of routes (bus numbers) and the second is the set of predictions for that route. Since these are in an array, we can use some of the new ES6 functions to parse this out into a set of sentences for each route.&lt;/p&gt;

&lt;p&gt;Note: That routes with no predictions will show up as empty arrays, so we have to &lt;code&gt;filter&lt;/code&gt; to get them out. Predictions with no value will show up as empty strings, and we can filter those out as well (even using the same &lt;code&gt;length&lt;/code&gt; check for both!)&lt;/p&gt;

&lt;p&gt;In the actual repo, I have this set up as a one-liner, but it's expanded/annotated below:&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;exports&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;stringifyPredictions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;results&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;joiner&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;. &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;resultsMessage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;results&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;predictionList&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;// predicitonList is a set of predictions for a route&lt;/span&gt;
    &lt;span class="c1"&gt;// Filter out the empty ones (empty strings), then join them together&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;predictionList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;l&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;l&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;joiner&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;

  &lt;span class="c1"&gt;// Filter and join again on the set of routes&lt;/span&gt;
  &lt;span class="c1"&gt;// Filtering out empty routes (which show up here as empty arrays)&lt;/span&gt;
  &lt;span class="nx"&gt;resultsMessage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;resultsMessage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;l&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;l&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;joiner&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;resultsMessage&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Make it web-accessible
&lt;/h2&gt;

&lt;p&gt;In order to work, Google Assistant must be able to access our service over the web, where we will return what we want it to say as a JSON response. I use &lt;a href="https://expressjs.com"&gt;Express&lt;/a&gt; to set up a server to listen to queries from Google, and host on Heroku.&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;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;express&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/thorndike&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&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;// See below for the contents of googleAction.js&lt;/span&gt;
  &lt;span class="nx"&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;./googleAction&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conversing with Google Assistant - Actions on Google and DialogFlow
&lt;/h2&gt;

&lt;p&gt;Now that we have functions for getting prediction sentences, we need to hook up Google Assistant to respond to our voice, and reach out to our service to get the set of predictions. For that we use the &lt;a href="https://www.npmjs.com/package/actions-on-google"&gt;&lt;code&gt;actions-on-google&lt;/code&gt;&lt;/a&gt; module from &lt;code&gt;npm&lt;/code&gt; as well as &lt;a href="https://dialogflow.com"&gt;Dialogflow&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Before getting into code, we need to set up our app on the Google Developer Console and Dialogflow. Dialogflow is the glue between Google Assistant and our app, it receives the parsed voice input from Google Assistant, and will call our app via webhook (they call it a "Fulfillment") in response. &lt;a href="https://developers.google.com/actions/dialogflow/first-app"&gt;I used this bit of documentation to get all of this set up&lt;/a&gt;. It goes over some of the concepts of a Google Assistant "conversation" as well has walking through the Dialogflow web console.&lt;/p&gt;

&lt;p&gt;Part of said setup is making an "Action" that the service can respond to. This can be any sort of string that identifies what's happening; we just need to remember is when we get to coding up our response. Another important part is the "argument," which is a piece of the spoken phrase that can be variable. We can extract that text and use that to inform which bus we are looking for. E.g. "Hey Google, What buses are near &lt;strong&gt;Harvard&lt;/strong&gt;?" Both of these will get sent to our request handler, which is the next bit of code we will be working on!&lt;/p&gt;

&lt;h2&gt;
  
  
  Responding to requests with &lt;code&gt;actions-on-google&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;The &lt;a href="https://www.npmjs.com/package/actions-on-google"&gt;&lt;code&gt;actions-on-google&lt;/code&gt; module&lt;/a&gt; works by parsing the request received from Google Assistant/Dialog flow, and calling a function based on what action was sent. This is done by setting up a Map that connects action strings to functions. From there we just have to call &lt;code&gt;getPredictions&lt;/code&gt;/&lt;code&gt;stringifyPredictions&lt;/code&gt; to get our prediction sentences, and then pass that into a &lt;code&gt;tell&lt;/code&gt; function that &lt;code&gt;actions-on-google&lt;/code&gt; gives us!&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;// googleAction.js&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&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;actions-on-google&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;DialogflowApp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;getPredictions&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;stringifyPredictions&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&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;./getPredictions&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// This is the action we set up in DialogFlow&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ASK_ACTION&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ask_stop_by_name&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// We set up a parameter called stop_name, that is filled in&lt;/span&gt;
&lt;span class="c1"&gt;// when the voice input is parsed.&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;STOP_NAME_ARGUMENT&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;stop_name&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="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;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;actionMap&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Map&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="nx"&gt;actionMap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ASK_ACTION&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;app&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;// getArgument() is a function from &lt;/span&gt;
    &lt;span class="c1"&gt;// `actions-on-google` / `DialogflowApp` that can parse&lt;/span&gt;
    &lt;span class="c1"&gt;// out the argument from the voice input.&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;stopName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getArgument&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;STOP_NAME_ARGUMENT&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nx"&gt;getPredictions&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;stopName&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;results&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;stringifyPredictions&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;results&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;resultsMessage&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;// stringifyPredictions returns 'false' if a stop exists, but has no buses.&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;resultsMessage&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

          &lt;span class="c1"&gt;// app.tell literally makes Google Assistant speak!&lt;/span&gt;
          &lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tell&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`There don't seem to be any buses at &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;stopName&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="c1"&gt;// any other falsy value means that the app doesn't know about that stop&lt;/span&gt;
        &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;resultsMessage&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tell&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Sorry, I don't have information for &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;stopName&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="c1"&gt;// We got some predictions!&lt;/span&gt;
        &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tell&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;resultsMessage&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="c1"&gt;// The App, built based on the request/response we received,&lt;/span&gt;
  &lt;span class="c1"&gt;// will take in our map, figure out the action based&lt;/span&gt;
  &lt;span class="c1"&gt;// on what Dialogflow sent us, and then call the&lt;/span&gt;
  &lt;span class="c1"&gt;// relevant function.&lt;/span&gt;
  &lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;handleRequest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;actionMap&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Talking with Google Assistant
&lt;/h2&gt;

&lt;p&gt;Now that we have our web app set up (and hosted, and the webhook is put into Dialogflow), we can start talking to our new Google Assistant app! There are just a few things to set up that will make talking to Google just a bit nicer.&lt;/p&gt;

&lt;h3&gt;
  
  
  Rename your app
&lt;/h3&gt;

&lt;p&gt;When setting up Dialogflow, it created an app in the &lt;a href="https://console.actions.google.com/"&gt;Actions on Google Console&lt;/a&gt;. We can log in here and update the App information, like the app name and pronunciation, so we can talk to our service by name. I called mine "Thorndike Next Bus" (more on naming in a bit).&lt;/p&gt;

&lt;p&gt;This screen is meant for putting in your app metadata for publishing on the Google Actions Marketplace for everyone to use. However I currently don't have plans for a general public release of this; I just want to use it on my account. But since we are effectively preparing a public app (just not releasing it), we have a few limitations.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;There are a number of required fields that don't apply, mostly related to marketing imagery and copy. You can leave these blank, and your info will save, however you'll get warnings everytime you return to make an update&lt;/li&gt;
&lt;li&gt;Since this is meant for a public release, the name of your app has to be unique (and also not related to an established brand, as Google will prompt you to prove that you are working on behalf of that brand, which you probably aren't). This means that your app's name might have to be an awkward phrase instead of a single word.&lt;/li&gt;
&lt;li&gt;Since we aren't "releasing" our Google Assistant app, she will constantly tell us that we are using the "test version" of our app. Oh well.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Testing in the browser
&lt;/h3&gt;

&lt;p&gt;Once you edit your app information, you can test out the responses in your browser by clicking "Test Draft". You'll get a screen that looks like the Google Assisant Android screen on the left, and various data about your tests on the right. Here, you can type in your expected voice input and see how Google Assistant responds.&lt;/p&gt;

&lt;p&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--9DI4eAtM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/s1k58y2rqskfdt4xpd05.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--9DI4eAtM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/s1k58y2rqskfdt4xpd05.png" alt="Testing Thorndike Next Bus"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Success!&lt;/em&gt;
&lt;/p&gt;

&lt;h3&gt;
  
  
  Testing with your voice
&lt;/h3&gt;

&lt;p&gt;Now that everything is deployed, you can actually talk with Google Assistant (as long as you are logged in to the same Google account as you made the app on) and follow a similar conversation as you saw above. Just say "Hey Google, Talk to " and you're ready to go.&lt;/p&gt;

&lt;h3&gt;
  
  
  Feels clunky? Yeah, it kind of is.
&lt;/h3&gt;

&lt;p&gt;The was Actions on Google works is through a concept of "conversations." Which is great for talking to an AI. However the fact that you have to retrieve a second "assistant" to get the information (instead of the info coming from Google Assistant herself) feels like a hiccup in the process. In the end, it adds an extra call/response to a procedure that could be shortened "Hey Google, get predictions for X bus." Going the "conversation" route is a bit longer, but it has the benefit of being completely hands-free.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Future
&lt;/h2&gt;

&lt;p&gt;This way of augmenting Google Assistant is fantastic for setting up conversations with AI to interact with data sources that don't come "standard" with it. Just takes a bit of work to mold the data into a sentence, and then serve a response when Google comes knocking on your server with some voice input. However, sometimes these conversations can be clunky just to get a bit of data. If only there were an alternative way to get the data, with a single sentence or even the press of a button…&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Oh wait there is!&lt;/strong&gt; In a followup article, I'll be hooking up the same bus tracking app to &lt;a href="https://ifttt.com/google_assistant"&gt;IFTTT's Google Assistant integration&lt;/a&gt;, which will allow us to access our data in a number of different alternative ways to Google's conversations. &lt;/p&gt;

</description>
    </item>
    <item>
      <title>What do you look for in a good developer article/tutorial?</title>
      <dc:creator>Steven Washington</dc:creator>
      <pubDate>Thu, 08 Feb 2018 22:45:00 +0000</pubDate>
      <link>https://forem.com/washingtonsteven/what-do-you-look-for-in-a-good-devto-articletutorial--5hen</link>
      <guid>https://forem.com/washingtonsteven/what-do-you-look-for-in-a-good-devto-articletutorial--5hen</guid>
      <description>&lt;p&gt;I've been sitting on an article (a Google Assistant tutorial) for a while, trying to groom it to be great! However I've been kind of stuck in a paralysis afraid of it not being &lt;em&gt;perfect&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;I know at some point I will have to just hit &lt;strong&gt;publish&lt;/strong&gt; and go for it, but I figured I'd ask the community...What are some good things to have in an article/tutorial that make the whole thing a joy to read and learn from?&lt;/p&gt;

</description>
      <category>discuss</category>
      <category>writing</category>
    </item>
    <item>
      <title>Snippet: All-CSS (scss) Arrow Circles for Your Pagination Needs</title>
      <dc:creator>Steven Washington</dc:creator>
      <pubDate>Mon, 11 Sep 2017 00:53:18 +0000</pubDate>
      <link>https://forem.com/washingtonsteven/snippet-all-css-scss-arrow-circles-for-your-pagination-needs</link>
      <guid>https://forem.com/washingtonsteven/snippet-all-css-scss-arrow-circles-for-your-pagination-needs</guid>
      <description>&lt;p&gt;So I just did this for my site and thought it was a fun and simple snippet to share. Nothing too fancy, but using only CSS for something presentational just makes me giddy!&lt;/p&gt;

&lt;p&gt;So here’s the markup:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"page-link prev"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"/prev"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/a&amp;gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"page-link next"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"/next"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/a&amp;gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Easy! Only slightly weird thing is that there is no text in the &lt;code&gt;a&lt;/code&gt; tags. We would probably want to add a &lt;code&gt;title&lt;/code&gt; attribute to the tag to make sure everyone knows what we are talking about.&lt;/p&gt;

&lt;p&gt;And the magic! In Sass (scss) because we’re being all &lt;em&gt;modern&lt;/em&gt;: (explanation in comments)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sass"&gt;&lt;code&gt;&lt;span class="nv"&gt;$circle_diameter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;50px&lt;/span&gt;&lt;span class="err"&gt;;&lt;/span&gt;
&lt;span class="nv"&gt;$dark_gray&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;rgba&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;74&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="m"&gt;77&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="m"&gt;81&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="err"&gt;;&lt;/span&gt;
&lt;span class="nv"&gt;$yellow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;rgba&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;255&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="m"&gt;199&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="err"&gt;;&lt;/span&gt;
&lt;span class="nc"&gt;.page-link&lt;/span&gt; &lt;span class="err"&gt;{&lt;/span&gt;
  &lt;span class="nt"&gt;a&lt;/span&gt; &lt;span class="err"&gt;{&lt;/span&gt; 
    &lt;span class="c1"&gt;// We will make this empty a tag a circle&lt;/span&gt;
    &lt;span class="c1"&gt;// Set equal width and height.&lt;/span&gt;
    &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;$circle_diameter&lt;/span&gt;&lt;span class="err"&gt;;&lt;/span&gt; 
    &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;$circle_diameter&lt;/span&gt;&lt;span class="err"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// This curves in the corners to make a circle.&lt;/span&gt;
    &lt;span class="nl"&gt;border-radius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="m"&gt;50%&lt;/span&gt;&lt;span class="err"&gt;;&lt;/span&gt; 

    &lt;span class="c1"&gt;// Make it look nice.&lt;/span&gt;
    &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nv"&gt;$yellow&lt;/span&gt;&lt;span class="err"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// We're going to be doing some funky positioning stuff!&lt;/span&gt;
    &lt;span class="nt"&gt;position&lt;/span&gt;&lt;span class="nd"&gt;:relative&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// Yes! We are using both :before and :after pseudoclasses! Each will be a "leg" of the arrow&lt;/span&gt;
    &lt;span class="k"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nd"&gt;:before&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="k"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nd"&gt;:after&lt;/span&gt; &lt;span class="err"&gt;{&lt;/span&gt; 
      &lt;span class="c1"&gt;// Gotta have this to make the pseudoclasses work.&lt;/span&gt;
      &lt;span class="nl"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="err"&gt;;&lt;/span&gt;
      &lt;span class="c1"&gt;// You can mess with these values to change how thick and long the arrow legs are.&lt;/span&gt;
      &lt;span class="c1"&gt;// But you will have to mess with positioning below, as well.&lt;/span&gt;
      &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="m"&gt;30%&lt;/span&gt;&lt;span class="err"&gt;;&lt;/span&gt;
      &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="m"&gt;12%&lt;/span&gt;&lt;span class="err"&gt;;&lt;/span&gt;
      &lt;span class="c1"&gt;// Something to contrast the $yellow.&lt;/span&gt;
      &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nv"&gt;$dark_gray&lt;/span&gt;&lt;span class="err"&gt;;&lt;/span&gt; 
      &lt;span class="c1"&gt;// Here it comes...&lt;/span&gt;
      &lt;span class="nt"&gt;position&lt;/span&gt;&lt;span class="nd"&gt;:absolute&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; 
      &lt;span class="c1"&gt;// Oh, just center it. &lt;/span&gt;
      &lt;span class="c1"&gt;// transform will take care of fine tuning the positioning.&lt;/span&gt;
      &lt;span class="nl"&gt;top&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="m"&gt;50%&lt;/span&gt;&lt;span class="err"&gt;;&lt;/span&gt; 
      &lt;span class="nl"&gt;left&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="m"&gt;50%&lt;/span&gt;&lt;span class="err"&gt;;&lt;/span&gt;
    &lt;span class="err"&gt;}&lt;/span&gt;
  &lt;span class="err"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;// Here's all the crazy positioning stuff, handled by the "transform" directive.&lt;/span&gt;
  &lt;span class="c1"&gt;// :before becomes the top of the arrow, and :after is the bottom (see the second param of translate()).&lt;/span&gt;
  &lt;span class="c1"&gt;// Note how the values flip between .prev and .next (and the first param in translate value flipping over -50%)!&lt;/span&gt;
  &lt;span class="c1"&gt;// You can tweak these values to make different angles of arrows! &lt;/span&gt;
  &lt;span class="c1"&gt;// But if you do you will probably have to change the size of the legs above.&lt;/span&gt;
  &lt;span class="k"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nc"&gt;.prev&lt;/span&gt; &lt;span class="err"&gt;{&lt;/span&gt;
    &lt;span class="nt"&gt;a&lt;/span&gt;&lt;span class="nd"&gt;:before&lt;/span&gt;&lt;span class="err"&gt;{&lt;/span&gt;
      &lt;span class="nt"&gt;transform&lt;/span&gt;&lt;span class="nd"&gt;:translate&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;-60&lt;/span&gt;&lt;span class="nv"&gt;%&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nt"&gt;-100&lt;/span&gt;&lt;span class="nv"&gt;%&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="nt"&gt;rotate&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;-45deg&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="err"&gt;}&lt;/span&gt;
    &lt;span class="nt"&gt;a&lt;/span&gt;&lt;span class="nd"&gt;:after&lt;/span&gt; &lt;span class="err"&gt;{&lt;/span&gt;
      &lt;span class="nt"&gt;transform&lt;/span&gt;&lt;span class="nd"&gt;:translate&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;-60&lt;/span&gt;&lt;span class="nv"&gt;%&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nt"&gt;0&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="nt"&gt;rotate&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;45deg&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="err"&gt;}&lt;/span&gt;
  &lt;span class="err"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;// Second verse, same as the first!&lt;/span&gt;
  &lt;span class="k"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nc"&gt;.next&lt;/span&gt; &lt;span class="err"&gt;{&lt;/span&gt;
    &lt;span class="nt"&gt;a&lt;/span&gt;&lt;span class="nd"&gt;:before&lt;/span&gt;&lt;span class="err"&gt;{&lt;/span&gt;
      &lt;span class="nt"&gt;transform&lt;/span&gt;&lt;span class="nd"&gt;:translate&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;-40&lt;/span&gt;&lt;span class="nv"&gt;%&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nt"&gt;-100&lt;/span&gt;&lt;span class="nv"&gt;%&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="nt"&gt;rotate&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;45deg&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="err"&gt;}&lt;/span&gt;
    &lt;span class="nt"&gt;a&lt;/span&gt;&lt;span class="nd"&gt;:after&lt;/span&gt; &lt;span class="err"&gt;{&lt;/span&gt;
      &lt;span class="nt"&gt;transform&lt;/span&gt;&lt;span class="nd"&gt;:translate&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;-40&lt;/span&gt;&lt;span class="nv"&gt;%&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nt"&gt;0&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="nt"&gt;rotate&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;-45deg&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="err"&gt;}&lt;/span&gt;
  &lt;span class="err"&gt;}&lt;/span&gt;
&lt;span class="err"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;:before&lt;/code&gt; and &lt;code&gt;:after&lt;/code&gt; pseudoclasses are a lifesaver here.&lt;/p&gt;

&lt;p&gt;And here’s what it all looks like in the end:&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/http%3A%2F%2Fwashingtonsteven.net%2Fwp-content%2Fuploads%2F2017%2F09%2FScreen-Shot-2017-09-10-at-8.31.17-PM.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/http%3A%2F%2Fwashingtonsteven.net%2Fwp-content%2Fuploads%2F2017%2F09%2FScreen-Shot-2017-09-10-at-8.31.17-PM.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Well, at least &lt;em&gt;I&lt;/em&gt; think it’s pretty neat.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This post was originally published on &lt;a href="http://washingtonsteven.net/snippet-all-css-scss-arrow-circles-for-your-pagination-needs/" rel="noopener noreferrer"&gt;washingtonsteven.net&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>snippets</category>
      <category>webdev</category>
      <category>codesnippet</category>
      <category>css</category>
    </item>
    <item>
      <title>Playing with Canvas and ES6 Classes</title>
      <dc:creator>Steven Washington</dc:creator>
      <pubDate>Sat, 09 Sep 2017 15:32:02 +0000</pubDate>
      <link>https://forem.com/washingtonsteven/playing-with-canvas-and-es6-classes</link>
      <guid>https://forem.com/washingtonsteven/playing-with-canvas-and-es6-classes</guid>
      <description>&lt;p&gt;&lt;em&gt;This is also available on my new blog &lt;a href="http://washingtonsteven.net/playing-with-canvas-and-es6-classes/"&gt;http://washingtonsteven.net/playing-with-canvas-and-es6-classes/&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  A Train Ride
&lt;/h2&gt;

&lt;p&gt;This past Labor Day weekend I took some time to take the train down to New York City with my wife to see the sights, eat some good food, and generally get incredibly overwhelmed by the sheer &lt;em&gt;denseness&lt;/em&gt; of the city. It's a great city and I know many people love it, but it's more and more becoming not my style. However on the way back I was actually awake enough to run through &lt;a href="http://www.somethinghitme.com/2013/01/09/creating-a-canvas-platformer-tutorial-part-one/"&gt;a quick tutorial&lt;/a&gt;Â on how to use the HTML5 Canvas API to draw to the screen, take in inputs and output a simple, single-screen platformer game. Nothing to write home about, but it was nice to get away from the libraries like &lt;a href="http://www.pixijs.com/"&gt;Pixi&lt;/a&gt; and &lt;a href="http://createjs.com/"&gt;CreateJS&lt;/a&gt; and just get your hands dirty directly.&lt;/p&gt;

&lt;h2&gt;
  
  
  A New Challenge
&lt;/h2&gt;

&lt;p&gt;The tutorial (linked above) turned out to be from 2013. Flipping through it, the javascript necessary to power the simple app was fairly straightforward, and the tutorial was less a lesson in Javascript and more a lesson in simple game programming: concepts of player variables, modeling the loop in memory then drawing it, and collisions (box-based, but still) were all covered. As someone with some experience building similar systems in Unity, this wasn't anything particularly new. But that Unity knowledge would drive me to update the code in this tutorial for something that is very useful in Unity's use of C#, and just about every other language except Javascript, until recently that is.&lt;/p&gt;

&lt;h2&gt;
  
  
  ES6 Classes
&lt;/h2&gt;

&lt;p&gt;The tutorial keeps all of the game state in the global &lt;code&gt;window&lt;/code&gt;Â object. Various other objects (like a &lt;code&gt;player&lt;/code&gt;Â object, or &lt;code&gt;boxes&lt;/code&gt;Â array) are top level, while items like handling input are added directly as needed. As a person that's constantly interested in keeping a clean and semantic codebase, I took the 3.5 hour ride (we were lucky enough to get Acela tickets) to try to refactor what the original author had done.&lt;/p&gt;

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

&lt;p&gt;Follow along with the code &lt;a href="https://github.com/washingtonsteven/js-canvas-platformer/tree/95927ec3ff837ff3128472370b3b9f7b48464341"&gt;on Github&lt;/a&gt;. I don't repeat every line here, so go check the full thing out! (Link goes to the specific commit that this post is referencing, since I will be updating it in the future).&lt;/p&gt;

&lt;h3&gt;
  
  
  Main class
&lt;/h3&gt;

&lt;p&gt;I started off with a main class, that really just kicked everything off. I've had a habit of doing something like:&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;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;ready&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;main&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;init&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;main&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;init&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// actually do stuff here&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It kept things out of the global scope, at least. But not nearly ES6-y enough. Also...still relying on jQuery? &lt;a href="https://meta.stackoverflow.com/questions/335328/when-is-use-jquery-not-a-valid-answer-to-a-javascript-question"&gt;That's so 2010&lt;/a&gt;. Now we can shed that pile of bloat&lt;sup&gt;1&lt;/sup&gt; and in a fairly easy-to-read way setup our main starter class: the &lt;code&gt;public static void main(String [] args)&lt;/code&gt; of Javascript.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;    &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;CVS&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="c1"&gt;//CVS is short for canvas, not a convenience store/pharmacy&lt;/span&gt;
      &lt;span class="kd"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// actually do stuff here&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;  
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;cvs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;CVS&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;
  
  
  Browserify
&lt;/h3&gt;

&lt;p&gt;Javascript isn't great about sharing resources between files. At least in the browser, you either need to concatenate all your work into a single file (which you should do for production, but is a pain in dev), or add a bunch of &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; tags (for those who really don't care about HTTP requests). Fortunately, you can work in separate files and a huge number of packages (&lt;code&gt;gulp&lt;/code&gt;, &lt;code&gt;browserify&lt;/code&gt;, and &lt;code&gt;webpack&lt;/code&gt;, to name a few) will do all the concatenating work for you. What's even better is that with some you can even declare which files you want to use in Javascript itself, with the use of modules. All you need is a &lt;code&gt;require&lt;/code&gt; and boom, you have resources from another file.&lt;/p&gt;

&lt;h3&gt;
  
  
  Player class
&lt;/h3&gt;

&lt;p&gt;For example, the &lt;code&gt;Player&lt;/code&gt; should have its own class where it can keep track of it's own variables (position, velocity, and size, among others). For sanity's sake, we will separate that out into a separate file to keep the code base organized (and prevent collisions in scm). Luckily ES6 gives us a default (&lt;em&gt;fingerguns&lt;/em&gt;) way to expose a class&lt;/p&gt;

&lt;h4&gt;
  
  
  player.js
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;    &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;Player&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;x&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="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;//etc., etc.&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;

      &lt;span class="nx"&gt;move&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;horizontal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;vertical&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// given the horizontal and vertical input directions, move the player in this frame by updating this.x and this.y&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;

      &lt;span class="nx"&gt;draw&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Given a canvas 2d context, draw the player at the current position (this.x, this.y). &lt;/span&gt;
        &lt;span class="c1"&gt;// For simplicity's sake, this player is a square and we can use the canvas rect() function&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;Player&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That last line is the magic&lt;sup&gt;2&lt;/sup&gt;. We now can export the class (which is actually a function, since &lt;code&gt;class&lt;/code&gt; is just syntactic sugar for JS prototypical "class" definition, and not truly a "new" spec.&lt;/p&gt;

&lt;h3&gt;
  
  
  Collisions! (util.js)
&lt;/h3&gt;

&lt;p&gt;It's hard to have a game without checking for collisions! The end of &lt;code&gt;util.js&lt;/code&gt; (which isn't really a class, just an object with a collection of functions) has some basic math for checking for collisions between two objects. I won't go into the math of it (the tutorial linked above does a good job of that). But it can detect if two objects have collided as long as both can describe a rectangle, that is, they have an &lt;code&gt;x&lt;/code&gt; and &lt;code&gt;y&lt;/code&gt; position, and &lt;code&gt;width&lt;/code&gt; and &lt;code&gt;height&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Other classes
&lt;/h3&gt;

&lt;h4&gt;
  
  
  input.js
&lt;/h4&gt;

&lt;p&gt;Having an input class (which basically is a Singleton, like Player above), is useful to send input events to the appropriate place. The Player doesn't need to know anything about what keys were pressed, just what direction we need to go! So we abstract that away from them. This even allows the flexibility to swap out what kind of inputs we are using: keyboard, mouse, Wiimote, and even mind control&lt;sup&gt;3&lt;/sup&gt; are all possible!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;    &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;Input&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;docBody&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="c1"&gt;//pass in a reference to document.body&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;keys&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;
        &lt;span class="nx"&gt;docBody&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;keydown&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;keyCode&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;span class="p"&gt;});&lt;/span&gt;
        &lt;span class="nx"&gt;docBody&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;keyup&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;keyCode&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is the meat of &lt;code&gt;Input&lt;/code&gt;. An array keeps track of which keys are pressed. And anyone with access to an Input instance can just check &lt;code&gt;Input.keys&lt;/code&gt; and see what keys are pressed at any given moment. Any other functions on this class (for now) are just fluff to make checking easier.&lt;/p&gt;

&lt;p&gt;As I'm writing this, I realize that an update for this is to make Input a true singleton. Right now you can have multiple versions of this class which can be a mess. For the most part, I think you'd only need one.&lt;/p&gt;

&lt;h4&gt;
  
  
  platform.js and level.js (and coin.js!)
&lt;/h4&gt;

&lt;p&gt;&lt;code&gt;Platform&lt;/code&gt; is basically a glorified rectangle with a &lt;code&gt;draw&lt;/code&gt; function. Pass it a canvas context and it'll draw a &lt;code&gt;rect&lt;/code&gt; onto it with it's own internal state (&lt;code&gt;x&lt;/code&gt;, &lt;code&gt;y&lt;/code&gt;, &lt;code&gt;width&lt;/code&gt;, and &lt;code&gt;height&lt;/code&gt;). Coins are the same, except they are circles, and have a &lt;code&gt;collected&lt;/code&gt; state that will gray them out the next time they are drawn.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Level&lt;/code&gt; is a collection of platforms. If you tell a level to draw itself, it just passes on the command to it's array of platforms (and coins).&lt;/p&gt;

&lt;h4&gt;
  
  
  (The rest of) util.js
&lt;/h4&gt;

&lt;p&gt;The rest of util has some nice helper functions to get us through the hard times (and keeping things DRY)&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;code&gt;normalize(num)&lt;/code&gt;: Sometimes, we don't care about the value of a variable, just whether it is less than zero, zero or greater than zero. Here's a quickie to do that. (Don't tell me, there's a &lt;code&gt;Math&lt;/code&gt; function that already does this in Javascript)&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;clamp(num, min, max)&lt;/code&gt;: Instead of having boundary checks everywhere, here we can just pass a number in, and either get that number back, or &lt;code&gt;min&lt;/code&gt; if it's less than &lt;code&gt;min&lt;/code&gt; or &lt;code&gt;max&lt;/code&gt; if it's less than &lt;code&gt;max&lt;/code&gt;. In addition there's some simple checks so that &lt;code&gt;min&lt;/code&gt; and &lt;code&gt;max&lt;/code&gt; can be passed in any order, and if you only pass a single boundary, it will assume that that is &lt;code&gt;max&lt;/code&gt; and &lt;code&gt;min&lt;/code&gt; is negative &lt;code&gt;max&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;not(o)&lt;/code&gt;: Just a simple way to check for existence without having to weed out 'falsy' values each time.&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;objectHasAllProps(o, props)&lt;/code&gt; (and &lt;code&gt;objectsHaveAllProps&lt;/code&gt;): Just used for &lt;code&gt;collide&lt;/code&gt;, it's something of a type checker in a language where types don't exist Â¯\_(ãƒ„)_/Â¯. Added a plural version because.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Round 2, start!
&lt;/h3&gt;

&lt;p&gt;So that's the first pass at it (at least a brief overview, anyway). It was a lot of fun to go through and make this work with this new tool I'm learning about! The next step is implementing more complex levels, possibly getting out of the drawing API and working with actual images, and throwing it all away and just using a canvas library like Pixi.js because I ain't got time to write my own.&lt;/p&gt;

&lt;p&gt;Once again, follow the code (at the time of this post) &lt;a href="https://github.com/washingtonsteven/js-canvas-platformer/tree/95927ec3ff837ff3128472370b3b9f7b48464341"&gt;on Github&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;&lt;a&gt;1.&lt;/a&gt; jQuery has it's uses, of course. But I always try to see how long I can go before having to use it.&lt;/p&gt;

&lt;p&gt;&lt;a&gt;2.&lt;/a&gt; Tools like &lt;a href="https://babeljs.io/"&gt;Babel&lt;/a&gt; have made exporting/importing variables weird, since Babel &amp;lt; 6.0 suppressed errors for some technically invalid code. &lt;a href="https://medium.com/@kentcdodds/misunderstanding-es6-modules-upgrading-babel-tears-and-a-solution-ad2d5ab93ce0"&gt;Read more here.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a&gt;3.&lt;/a&gt; Mind Control API coming ~2020?&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>canvas</category>
      <category>es6</category>
      <category>devlog</category>
    </item>
    <item>
      <title>Is Apple really needed?</title>
      <dc:creator>Steven Washington</dc:creator>
      <pubDate>Mon, 28 Aug 2017 14:45:02 +0000</pubDate>
      <link>https://forem.com/washingtonsteven/is-apple-really-needed</link>
      <guid>https://forem.com/washingtonsteven/is-apple-really-needed</guid>
      <description>&lt;p&gt;So it seems that Apple has a large share of use in the web development community, particularly because of it's Unix-like-ness and it's ease of use for the common user. It would seem that would make it a great choice for IT to roll across the company; devs get a Unix-like machine and everyone else gets a simple machine to use.&lt;/p&gt;

&lt;p&gt;But for hobby developers, is there anything locking you to Apple? &lt;strong&gt;Any utility or tool that is a &lt;em&gt;must-have&lt;/em&gt; that is only available on Mac and not Linux?&lt;/strong&gt; Or would it be just fine to get a cheap machine with Linux and call it a day?&lt;/p&gt;

&lt;p&gt;Apologies for any platforms wars this erupts...&lt;/p&gt;

</description>
      <category>discuss</category>
      <category>webdev</category>
      <category>mac</category>
      <category>linux</category>
    </item>
    <item>
      <title>Hi, I'm Steven Washington</title>
      <dc:creator>Steven Washington</dc:creator>
      <pubDate>Wed, 21 Jun 2017 07:45:44 +0000</pubDate>
      <link>https://forem.com/washingtonsteven/hi-im-steven-washington</link>
      <guid>https://forem.com/washingtonsteven/hi-im-steven-washington</guid>
      <description>&lt;p&gt;I have been coding for 15 years.&lt;/p&gt;

&lt;p&gt;You can find me on GitHub as &lt;a href="https://github.com/washingtonsteven" rel="noopener noreferrer"&gt;washingtonsteven&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I live in Boston.&lt;/p&gt;

&lt;p&gt;I work for Connelly Partners&lt;/p&gt;

&lt;p&gt;I mostly program in these languages: JS/PHP/C#.&lt;/p&gt;

&lt;p&gt;I am currently learning more about MEAN stack and Unity for 2D game development.&lt;/p&gt;

&lt;p&gt;Nice to meet you.&lt;/p&gt;

</description>
      <category>introduction</category>
    </item>
  </channel>
</rss>
