<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Rane Wallin</title>
    <description>The latest articles on DEV Community by Rane Wallin (@ranewallin).</description>
    <link>https://dev.to/ranewallin</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%2F155130%2F74d6bdee-09d0-496e-bcb1-2ef4302da1e6.png</url>
      <title>DEV Community: Rane Wallin</title>
      <link>https://dev.to/ranewallin</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ranewallin"/>
    <language>en</language>
    <item>
      <title>Let's make a Twitter bot! (Part I)</title>
      <dc:creator>Rane Wallin</dc:creator>
      <pubDate>Fri, 18 Oct 2019 13:28:10 +0000</pubDate>
      <link>https://dev.to/ranewallin/let-s-make-a-twitter-bot-part-i-232h</link>
      <guid>https://dev.to/ranewallin/let-s-make-a-twitter-bot-part-i-232h</guid>
      <description>&lt;p&gt;If you've spent much time on Twitter you've likely encountered a Twitter bot or two. A bot is merely a program that automatically interacts with the Twitter API. &lt;/p&gt;

&lt;p&gt;Twitter bots can be useful, irritating, entertaining, or just plain silly. If you've ever thought of making your own Twitter bot but didn't know where to start, you're in the right place! We're going to make a simple Twitter bot using free resources.&lt;/p&gt;

&lt;p&gt;In part I of this tutorial, we will focus setting up the various accounts you will need and getting your first automated status update posted to Twitter.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Things you'll need&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A &lt;a href="https://twitter.com"&gt;Twitter account&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;A &lt;a href="https://glitch.com/"&gt;Glitch account&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://app.getpostman.com/app/download/win64"&gt;Postman&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;Some basic JavaScript knowledge&lt;/li&gt;
&lt;li&gt;(For part II) Some kind of content for your bot&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Getting set up on Twitter
&lt;/h2&gt;

&lt;p&gt;Before you can do anything else, you need a Twitter developer account. If you don't yet have one, here are the steps.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Create a new Twitter account or log into an existing one that you wish to use.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Once logged into a Twitter account, go to the &lt;a href="https://developer.twitter.com/"&gt;Twitter Developer site&lt;/a&gt; at &lt;a href="https://developer.twitter.com/"&gt;https://developer.twitter.com/&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Click "Apply"&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--A_f6sDTz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/khp0opwejgauiyah36fn.JPG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--A_f6sDTz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/khp0opwejgauiyah36fn.JPG" alt='A screenshot of the Twitter developer site with an arrow pointing to the "Apply" link in the top right corner'&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;On the next page, click on "Apply for a developer account"&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You'll be given a few different options. For the purposes of this tutorial, I recommend selecting "Making a bot" under "Hobbyist." Click "Next" after making your selection(s).&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--cDvZYp5n--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/fh76m0nqq464tcfz3zhc.JPG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--cDvZYp5n--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/fh76m0nqq464tcfz3zhc.JPG" alt='The "Making a bot" option selected, showing a green check mark in the top right corner'&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;On the next page, verify your information is correct and fill out the required information (your country and name). Click "Next."&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Next you will be asked to provide details about how you intend to use the API. Select the options you will need and answer the required questions. For this tutorial I have only selected "Yes" for the question "Will your app use Tweet, Retweet, like, follow, or Direct Message functionality?" Depending on your needs, you may select other options. Click "Next."&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Verify everything is correct and click "Looks good!"&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Read and agree to the developer agreement (or don't, end tutorial, have a nice day!)&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;em&gt;NB: If you do not have a phone number connected to your Twitter account, you will need one to continue your setup at some point.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Once you have completed the developer application you will need to click a link in your email to verify your email address. &lt;/p&gt;

&lt;p&gt;We are not done with the developer site just yet, but you will need to do some setup on Glitch (your bot host) before you can continue with the rest.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting up your bot host
&lt;/h2&gt;

&lt;p&gt;Getting your developer application submitted and approved is just the first step. Now you need to create the app that will be connected to your bot, but in order to do that you need to have your bot's website URL. So, let's take a moment to set that up.&lt;/p&gt;

&lt;p&gt;If you don't already have a &lt;a href="https://glitch.com"&gt;Glitch&lt;/a&gt; account, go create one now and then come back here.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;After you have your account, go to &lt;a href="https://glitch.com/edit/#!/twitterbot?path=README.md:1:0"&gt;this template&lt;/a&gt; on the Glitch site. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;In the top right corner, click the button that says "Remix to Edit" to create a copy on your account.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--u66WsAsL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/8fbl7atxreheiskosz9r.JPG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--u66WsAsL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/8fbl7atxreheiskosz9r.JPG" alt='A screenshot showing the "Remix to Edit" button in the top right corner of the page'&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;After Glitch is done creating your site, click the button in the top left that says "Show" and then "In a new window". Copy the URL from this page or keep it open while moving on to the next section.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Creating your Twitter bot's app
&lt;/h2&gt;

&lt;p&gt;Okay, now that you have a URL for your bot's website, you can finish setting things up on the Twitter side.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Go back to &lt;a href="https://developer.twitter.com"&gt;developer.twitter.com&lt;/a&gt; and mouseover your name in the top right corner. Select "Apps."&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;On the Apps page, click "Create an app"&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Fill out the information about your app, pasting your new URL in the Website URL box. For this project we do not need to use the Twitter sign in API. I recommend leaving any non-required fields blank.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Click "Create" and then "Create" again.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Awesome! Your app has been created. Now you just need to get the API keys for your app and add them to your configuration file on Glitch. &lt;/p&gt;

&lt;h2&gt;
  
  
  Connecting your bot to Twitter
&lt;/h2&gt;

&lt;p&gt;Before you can actually interact with the Twitter API, you need to setup your Glitch environment with the API keys. &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;On the Twitter developer site, in your app's details page (the page you were taken to after creating the app) there is a tab at the top called "Keys and tokens," click it.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s---krhMbuu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/bedor54e2rtixmodcess.JPG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s---krhMbuu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/bedor54e2rtixmodcess.JPG" alt='A screenshot of the app details page showing the "Keys and tokens" tab'&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;In another tab or window, open your Glitch project and click on the .env file. You should see a file opened in the right hand side that has a spot for all your API keys.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--rlmUgbEr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/7j7g40tgjdcw04hhlan7.JPG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--rlmUgbEr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/7j7g40tgjdcw04hhlan7.JPG" alt="A screenshot showing the .env file and the location of the API keys in the Glitch environment"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Copy and paste the keys from the Twitter developer page to the corresponding location in the .env file. You will need to click "Create" under the "Access token &amp;amp; access token secret" section to generate those values. You do &lt;em&gt;not&lt;/em&gt; need to put the keys in quotes.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You will also see a spot in the .env file for &lt;code&gt;BOT_ENDPOINT&lt;/code&gt;. This is what you will put after the slash in your URL to trigger your bot. This will be explained in more detail later. You can put anything you want for this value.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--moBNHCiL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/5sdlh1vtxc00rqd2q0wx.JPG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--moBNHCiL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/5sdlh1vtxc00rqd2q0wx.JPG" alt="A screenshot showing the .env file after all the values have been filled in"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;We're almost there, I promise!&lt;/p&gt;

&lt;h2&gt;
  
  
  Sending your first automated Tweet
&lt;/h2&gt;

&lt;p&gt;Great news, you are done with all the configuration stuff. Now you can start using your server to interact with the Twitter API. The template you used already comes with some basic stuff set up, so we will focus on that for now.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;In your Glitch project, click on the "server.js" file and read through the code that is already there. You will see that it's already set up to send a simple "Hello world" post. So let's do it!&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Open Postman and select the get request type. Put in your project URL plus the bot endpoint you created. (Note: You can also just put this URL into your browser's address bar, but as you build out your bot it will be easier to use Postman.)&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--5xNUYkZu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/wpgq20naywdtwcdb91y7.JPG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--5xNUYkZu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/wpgq20naywdtwcdb91y7.JPG" alt="A screenshot showing the Postman interface"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Click "Send." If everything has been set up correctly, you should see a "Hello world" post on your bot's Twitter timeline.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--yKBTneFw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/j9u7b3whbcqnuwuy4gme.JPG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--yKBTneFw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/j9u7b3whbcqnuwuy4gme.JPG" alt='Screenshot of "Hello world" on twitter'&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Congratulations, you've just successfully sent a Tweet using the Twitter API, but it's not a bot yet. In order to be a bot it needs to be automated, so let's do that.&lt;/p&gt;

&lt;h2&gt;
  
  
  Making it a bot
&lt;/h2&gt;

&lt;p&gt;In order to make your app a bot, the process of hitting your endpoint needs to be automated. There are several free tools you can use to accomplish this. For this tutorial, I will be using &lt;a href="https://uptimerobot.com"&gt;UptimeRobot.com&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;UptimeRobot allows you to access a URL at a set interval that you decide. It will provide a status result in the dashboard indicating if the URL was accessible or not. This is often used to verify that a site is active, but you are going to use it to automatically trigger your bot.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Go to &lt;a href="https://uptimerobot.com"&gt;UptimeRobot.com&lt;/a&gt; and create an account (or log in if you already have an account).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;From your account dashboard, click the "Add New Monitor" button.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--YRErb4eG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/ul72clnqzp75n16e141b.JPG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--YRErb4eG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/ul72clnqzp75n16e141b.JPG" alt="Screenshot of the UptimeRobot dashboard showing the Add New Monitor button"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Select "HTTP(s)" for the monitor type&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Provide a "Friendly Name," which is the name that will show on your dashboard, and your endpoint URL. Remember, the endpoint URL is your Glitch URL followed by slash and whatever you set for the BOT_ENDPOINT in your .env file (i.e. something like &lt;code&gt;https://funky-ricecake.glitch.com/MyAmazingBot456&lt;/code&gt;).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Set an interval time. In order to comply with Glitch's terms of service, this should be an interval no less than 25 minutes. Depending on your bot, you can decide how often it should send a message. In the screenshot below, I have set the interval to once every 24 hours. This is the longest monitoring interval that UptimeRobot allows. If you want it to happen less often (i.e. once a week, once a month, etc) you may wish to find a different service.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--0QvnhMof--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/3v9fmq2b6rg1njdo4c2s.JPG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--0QvnhMof--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/3v9fmq2b6rg1njdo4c2s.JPG" alt="Screenshot from UptimeRobot.com showing the new monitor dialogue box"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;As soon as you click "Create Monitor" UptimeRobot will send the first request to your bot and the first automated status will be posted (which, unless you've already made some changes, will still be "hello world"). If you are not ready for your bot to make a post, you can wait until you have finished setting it up to create the monitor.&lt;/p&gt;




&lt;p&gt;That's it! At this point you should have a bot that can post a status update. Now, I'm sure that you would like your bot to do more than say "hello world" every day (or, maybe not, you do you). If so, please keep an eye out for part II of this tutorial where we will get some data from some open source APIs and use it to create slightly more interesting Twitter updates.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.flickr.com/photos/peyri/48825808/in/photolist-5jfdh-9X9Em-5jfek-rG9Fqw-626SgT-aWfwuk-7ka5Vz-d2EUi-253i2q8-66EEor-9zpYpp-6gLCqZ-7UCbw1-6hMJVU-PYXb6-9Yss3X-9pjpEw-7Puamg-6sGsY3-B1Vr8-aErH4u-6hMJEj-c1z2Fo-6KZEKf-926Ggh-b53aYD-bhNSLR-a1Qb1Q-e2HuW2-7LrZon-6J8xRT-bWFd4x-4gPheP-c2mmos-rNksgk-7t5BDs-5VpEr-6hHzvc-4YAkPo-GoM76-nxPg3-7vLqsV-6hHz64-41Htpk-ab9iZY-9XDEo-a6z7Kp-9BCdMc-wdYcV-4KZkx7"&gt;Cover image by Peyri Herrera on Flickr&lt;/a&gt;&lt;/p&gt;

</description>
      <category>twitter</category>
      <category>bot</category>
      <category>node</category>
    </item>
    <item>
      <title>How to keep your forked repository current</title>
      <dc:creator>Rane Wallin</dc:creator>
      <pubDate>Thu, 03 Oct 2019 14:51:21 +0000</pubDate>
      <link>https://dev.to/ranewallin/how-to-keep-your-forked-repository-current-38mn</link>
      <guid>https://dev.to/ranewallin/how-to-keep-your-forked-repository-current-38mn</guid>
      <description>&lt;p&gt;Are you new to open source? If so, hopefully you have taken advantage of Hacktoberfest to get your feet wet. It's an exciting feeling to get your first pull request merged into a big project, but what happens next? If you want to keep working on the project, you will need to keep your fork current. &lt;/p&gt;

&lt;p&gt;Here are some quick instructions on how to do that from beginning to end.&lt;/p&gt;

&lt;p&gt;h/t to &lt;a href="https://help.github.com/en/articles/syncing-a-fork"&gt;GitHub&lt;/a&gt; for having very clear instructions on this already. Here's all the steps in one place.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# If you haven't already added an upstream source, set your upstream&lt;/span&gt;
&lt;span class="c"&gt;# to the fork's original source&lt;/span&gt;
git remote add upstream &amp;lt;url_to_original&amp;gt;

&lt;span class="c"&gt;# Verify upstream is correct, you should see the URL for the upstream fetch and push&lt;/span&gt;
git remote &lt;span class="nt"&gt;-v&lt;/span&gt;

&lt;span class="c"&gt;# Get all recent branches and commits from the upstream&lt;/span&gt;
git fetch upstream

&lt;span class="c"&gt;# Check out your current master branch&lt;/span&gt;
git checkout master

&lt;span class="c"&gt;# Merge the branches and commits from the upstream&lt;/span&gt;
git merge upstream/master

&lt;span class="c"&gt;# Push the updated master to your forked remote repository&lt;/span&gt;
git push origin master
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;That's it. You should be up to date and ready to make your next PR.&lt;/p&gt;

&lt;p&gt;Cover image by &lt;a href="https://www.flickr.com/photos/salvatore-g2/6502103781/in/photolist-aUyYVB-4R7yio-au5gH-fw15QF-YE4VY-4NvSeT-au5gT-7HqX7-Mut76-MQ94U-MQreg-WqgKMd-oQFPi-CnvRni-ANpaTt-CLpBce-TLRHjw-fpk3Fx-depfqa-VGpkY8-8UafBR-6xBhJN-7Tc4Kk-25ix6bK-4PyFfg-29dUFMX-K2To4-8HZ5rP-6wVjWS-aUyYEz-btAkzZ-9tqNGh-2cSTEd3-amjMNb-RrQkeh-5W6g-93Zrtv-bKr1kg-b1KcJg-NtcAk-GboJn-rNnS8-d79Wph-9sRHm6-pkSL7-dUQ5nM-XQVUGm-spBcvQ-UaCf3T-bdqvEe"&gt;Salvatore G2 on Flickr&lt;/a&gt;&lt;/p&gt;

</description>
      <category>hacktoberfest</category>
      <category>git</category>
      <category>opensource</category>
    </item>
    <item>
      <title>This simple math hack lets you create an image carousel without any if statements</title>
      <dc:creator>Rane Wallin</dc:creator>
      <pubDate>Wed, 25 Sep 2019 01:52:06 +0000</pubDate>
      <link>https://dev.to/ranewallin/this-simple-math-hack-lets-you-create-an-image-carousel-without-any-if-statements-5chj</link>
      <guid>https://dev.to/ranewallin/this-simple-math-hack-lets-you-create-an-image-carousel-without-any-if-statements-5chj</guid>
      <description>&lt;p&gt;If you are a web developer or a web developer student, you have probably made at least one image carousel in your career. In fact, you've probably made a few. While there are plenty of image carousel libraries out there, sometimes you want (or need) to make it from scratch. &lt;/p&gt;

&lt;p&gt;Most image carousels are made from arrays of image data. When some event triggers a change (a timeout, button click, etc) the current image data is replaced with the next element in the array. The tricky part for many comes when they reach the end of the array. Now what? If you've been writing complex if statements trying to check for this condition, I'm here to tell you there's a better way.&lt;/p&gt;

&lt;p&gt;Observe the code 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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;imageData&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;image1.png&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;img2.png&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;img3.png&lt;/span&gt;&lt;span class="dl"&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;currentImage&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleImageChange&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;currentImage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;currentImage&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="nx"&gt;imageData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it. That's the whole thing. (Explanation below amazed Keanu.)&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%2Fqnhnybjm1e9ktzmg2zpr.jpg" 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%2Fqnhnybjm1e9ktzmg2zpr.jpg" alt="Keanu Reeves looking dumbfounded, or maybe just dumb"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  How it works
&lt;/h2&gt;

&lt;p&gt;Let's assume we have an array of 10 elements. Modulo division (what happens when you use the &lt;code&gt;%&lt;/code&gt; operator) returns the remainder of the division. If &lt;code&gt;currentImage&lt;/code&gt; is 0, then &lt;code&gt;(0 + 1) % 10&lt;/code&gt; is the remainder of &lt;code&gt;1/10&lt;/code&gt;, which is 1. This is because we cannot actually divide 1 by 10, so the whole dang 1 is left over. The same is true of 2 - 9. None of these numbers can be divided by 10, so the number itself is the remainder. The magic happens when we get to 10. &lt;/p&gt;

&lt;p&gt;Since our array is zero-index, there is no tenth element. This works in our favor! When you divide a number by itself, the remainder is 0, which means our &lt;code&gt;currentImage&lt;/code&gt; will be set to 0. This means that as soon as we get past the end of our array, its going to go back to the beginning. Nifty, yeah?&lt;/p&gt;

&lt;p&gt;In computer science, this is known as a circular array. The array itself is just a plain ole array, but we use this math trick to allow it to loop indefinitely.&lt;/p&gt;

&lt;p&gt;But, wait! What if we want to go the other way? Don't worry, I got you!&lt;/p&gt;

&lt;p&gt;We can do the same thing in reverse. The formula for this is  &lt;code&gt;(currentValue - 1 + totalElements) % totalElements&lt;/code&gt;. If we add this to the above example, it could look something like this.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;imageData&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;image1.png&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;img2.png&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;img3.png&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;currentImage&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleImageChange&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;direction&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;direction&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;forward&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nx"&gt;currentImage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;currentImage&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="nx"&gt;imageData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;else&lt;/span&gt;
    &lt;span class="nx"&gt;currentImage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;currentImage&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;imageData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="nx"&gt;imageData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I know, I know, I said there wouldn't be any &lt;code&gt;if&lt;/code&gt; statements, and there aren't, at least not for actually moving forward and back through the elements. We just need to know which direction to go.&lt;/p&gt;

&lt;p&gt;This isn't just great for image carousels. Any time you need to increment through an array one element at a time, this will eliminate any condition checking to see if you are at the end. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.flickr.com/photos/martinvirtualtours/2589290716/in/photolist-4WNMVo-8meden-4X98cR-npccaY-hMb4JG-CwyER-2auJs4-9fRWVK-evvmG4-9fS2bi-pDp7dm-5rhQu8-8sgGyD-78g8x9-5iRXxZ-98MPyx-3cos9k-dKVhfi-6KqcpM-7hEh3q-8cZX4X-6jPyNV-9MK7A5-7QphnS-dC2Ug7-zmh9j-aqH1Dv-duAefU-puJy5b-5CMBMj-RJTLLv-4mcRoX-2ctQi2a-e1CCBK-Qm7HEq-JEJbAP-KdTura-29Ayn7Y-j1mQi-C6Xc-2bRLJTV-bx2c3J-UpL74g-avkw7C-7QphV9-M5GUc-9fV5f9-98MPKH-2QABwu-7obWa" rel="noopener noreferrer"&gt;Cover image by Michael and Sherry Martin (flickr)&lt;/a&gt;&lt;/p&gt;

</description>
      <category>math</category>
      <category>cs</category>
      <category>javascript</category>
      <category>webdev</category>
    </item>
    <item>
      <title>JS Bites: React hook is called in a function which is neither a React function or [sic] a custom React Hook</title>
      <dc:creator>Rane Wallin</dc:creator>
      <pubDate>Tue, 24 Sep 2019 01:41:48 +0000</pubDate>
      <link>https://dev.to/ranewallin/js-bites-react-hook-is-called-in-a-function-which-is-neither-a-react-function-or-sic-a-custom-react-hook-1g2c</link>
      <guid>https://dev.to/ranewallin/js-bites-react-hook-is-called-in-a-function-which-is-neither-a-react-function-or-sic-a-custom-react-hook-1g2c</guid>
      <description>&lt;p&gt;So, you've decided to dive into React Hooks. Things have been going well (hopefully) until you get a mysterious error similar to the one 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="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;landingPage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setUser&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&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;span&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;Your&lt;/span&gt; &lt;span class="nx"&gt;users&lt;/span&gt; &lt;span class="nx"&gt;is&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/span&amp;gt; { user.name &lt;/span&gt;&lt;span class="err"&gt;}
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/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="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;landingPage&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;Error: React Hook "useState" is called in a function "landingPage" which is neither a React function or a custom React Hook function.&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Oh no! What happened? Setting aside the awful grammar in that error message, what else went wrong? It certainly looks like a React component. You've imported &lt;code&gt;React&lt;/code&gt;. You've imported &lt;code&gt;useState&lt;/code&gt;. You are exporting your function. Everything should be working, but it's not.&lt;/p&gt;

&lt;p&gt;Here's the gotcha, when you are using React Hooks, your functional component's name &lt;em&gt;MUST&lt;/em&gt; start with a capital letter. In this case, the function name is &lt;code&gt;landingPage&lt;/code&gt;. If you change it to &lt;code&gt;LandingPage&lt;/code&gt; it will work as expected.&lt;/p&gt;

&lt;p&gt;Likewise, if you are going to use a hook inside of a hook custom hook, the name of the custom hook &lt;em&gt;MUST&lt;/em&gt; start with "use" (lowercase).&lt;/p&gt;

&lt;p&gt;If you are wondering why, check out the &lt;a href="https://reactjs.org/docs/hooks-rules.html"&gt;React documentation&lt;/a&gt; on the subject.&lt;/p&gt;




&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; JS Bites

 Have you ever need a quick solution to a problem, but when you search 
 Google you are met with pages of tutorials and detailed instructions that 
 bury the information you need? That's what JS Bites attempts to solve. 
 Each post is a small, bite-sized primer on a very specific JS topic. The 
 aim is to provide enough detail to boost understanding, but not so much that 
 you become overwhelmed or lost.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

</description>
      <category>react</category>
      <category>javascript</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>JS Bites: Could not read something of undefined</title>
      <dc:creator>Rane Wallin</dc:creator>
      <pubDate>Sat, 21 Sep 2019 02:18:57 +0000</pubDate>
      <link>https://dev.to/ranewallin/js-bites-could-not-read-something-of-undefined-33i1</link>
      <guid>https://dev.to/ranewallin/js-bites-could-not-read-something-of-undefined-33i1</guid>
      <description>&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fk9hankvp6p9bjc7y3a52.JPG" 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%2Fk9hankvp6p9bjc7y3a52.JPG" alt="Error that reads "&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I tutor and mentor new developers in Javascript. By and large, the most common error they come across is "Cannot read some_property of undefined." An experienced developer will usually understand instantly what's gone wrong, but for new developers it can lead to sometimes &lt;em&gt;hours&lt;/em&gt; of frustration.&lt;/p&gt;

&lt;h3&gt;
  
  
  So, what does it really mean?
&lt;/h3&gt;

&lt;p&gt;In the most simple terms, this error means that a thing you are trying to access the properties on either does not exist or is not what you think it is.&lt;/p&gt;

&lt;p&gt;Here are a couple of examples&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;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;axios&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;API_URL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt; has been added to the database!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the above example, the front end team thought the back end would return a copy of the new user data in its response. In reality, the back end was just returning "Success." This results in the &lt;code&gt;console.log()&lt;/code&gt; returning an error that it &lt;code&gt;Cannot read name of undefined.&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;cats&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;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Grumpy&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Grey&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;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Heathcliff&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Orange&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Felix&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Black&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;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cats&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;grumpy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;color&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the above example, a new developer did not properly understand how to work with objects, particularly arrays of objects. &lt;/p&gt;

&lt;h3&gt;
  
  
  What to do when you see this error?
&lt;/h3&gt;

&lt;p&gt;Any time you are working with data, you should &lt;code&gt;console.log()&lt;/code&gt; the data before you start working with it, even when you are sure you know what it is. Once you see the data, it's often immediately clear what is going wrong.&lt;/p&gt;

&lt;p&gt;If I am passing data from one place to another (back end to front end, through React props, from one function to another, etc), I like to log out the data before it's passed and after. This allows me to confirm that things are passing through the way that I expect them to.&lt;/p&gt;

&lt;p&gt;You can also use an extension like Quokka, which allows you to see live code coverage and your &lt;code&gt;console.log()&lt;/code&gt;s right in your editor.&lt;/p&gt;

&lt;p&gt;The most important thing, though, is just keep coding. The more errors you see, the more errors you will eventually know how to fix. &lt;em&gt;People who have the answers have them because they once had the questions.&lt;/em&gt;&lt;/p&gt;




&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; JS Bites

 Have you ever need a quick solution to a problem, but when you search 
 Google you are met with pages of tutorials and detailed instructions that 
 bury the information you need? That's what JS Bites attempts to solve. 
 Each post is a small, bite-sized primer on a very specific JS topic. The 
 aim is to provide enough detail to boost understanding, but not so much that 
 you become overwhelmed or lost.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

</description>
      <category>javascript</category>
      <category>tutorial</category>
      <category>errors</category>
    </item>
    <item>
      <title>JS Bites: There might be a problem with the project dependency tree.</title>
      <dc:creator>Rane Wallin</dc:creator>
      <pubDate>Fri, 13 Sep 2019 15:59:52 +0000</pubDate>
      <link>https://dev.to/ranewallin/js-bites-there-might-be-a-problem-with-the-project-dependency-tree-59ho</link>
      <guid>https://dev.to/ranewallin/js-bites-there-might-be-a-problem-with-the-project-dependency-tree-59ho</guid>
      <description>&lt;p&gt;Sometimes when you try to install a React app you may get a long error that starts out like this:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;There might be a problem with the project dependency tree. It is&lt;br&gt;&lt;br&gt;
likely not a bug in Create React App, but something you need to fix&lt;br&gt;&lt;br&gt;
locally.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;You may also see the following bit of advice:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If prefer to ignore this check, add SKIP_PREFLIGHT_CHECK=true to an    .env file in your project. That will permanently disable this&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  So, what does this mean?
&lt;/h2&gt;

&lt;p&gt;The most likely cause is that you accidentally installed a package in a folder above your project folder. For instance, if you are in &lt;code&gt;/home/projects/my-project&lt;/code&gt; you may have accidentally installed a package into &lt;code&gt;/home/projects&lt;/code&gt; at some point. This is easy to do if you are on the command line and try to install a package before changing into the project directory.&lt;/p&gt;

&lt;p&gt;To resolve this, &lt;code&gt;cd ../&lt;/code&gt; into the directory above and do &lt;code&gt;ls&lt;/code&gt;. Do you see an incorrectly placed &lt;code&gt;node_modules&lt;/code&gt; and &lt;code&gt;package.json&lt;/code&gt;? If so, delete both. Otherwise, &lt;code&gt;cd ../&lt;/code&gt; and check again. Continue to do this until you find the errant installation.&lt;/p&gt;

&lt;p&gt;Once the errant installation has been deleted, return to your project directory, delete the node_modules there and try your install again.&lt;/p&gt;




&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; JS Bites

 Have you ever need a quick solution to a problem, but when you search 
 Google you are met with pages of tutorials and detailed instructions that 
 bury the information you need? That's what JS Bites attempts to solve. 
 Each post is a small, bite-sized primer on a very specific JS topic. The 
 aim is to provide enough detail to boost understanding, but not so much that 
 you become overwhelmed or lost.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

</description>
      <category>javascript</category>
      <category>npm</category>
      <category>react</category>
    </item>
    <item>
      <title>Getting started with the Waveshare 2.7" ePaper HAT on Raspberry Pi</title>
      <dc:creator>Rane Wallin</dc:creator>
      <pubDate>Fri, 30 Aug 2019 18:53:31 +0000</pubDate>
      <link>https://dev.to/ranewallin/getting-started-with-the-waveshare-2-7-epaper-hat-on-raspberry-pi-41m8</link>
      <guid>https://dev.to/ranewallin/getting-started-with-the-waveshare-2-7-epaper-hat-on-raspberry-pi-41m8</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;I have been curious about the Raspberry Pi for a long time, but I only started working with one recently when it was provided to me for a class I have this semester. The model I received is the Raspberry Pi 3 B+. RaspberryPi.org describes it as:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The Raspberry Pi 3 Model B+ is the latest product in the Raspberry Pi 3 range, boasting a 64-bit quad core processor running at 1.4 GHz, dual-band 2.4 GHz and 5 GHz wireless LAN, Bluetooth 4.2/BLE, faster Ethernet, and PoE capability via a separate PoE HAT&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;As soon as I received it I started looking at the various accessories and add-ons available. The selection of available displays caught my eye, and I decided I wanted to play with an eInk display. There are numerous eInk displays available for the Raspberry Pi. For my purposes, I chose the cheapest one I could find that didn't have terrible reviews.&lt;/p&gt;

&lt;h2&gt;
  
  
  The eInk display
&lt;/h2&gt;

&lt;p&gt;Waveshare Electronics offers a wide variety of add-ons for the Raspberry Pi, as well as other electronics. I was drawn to the &lt;a href="https://www.waveshare.com/2.7inch-e-Paper-HAT-B.htm" rel="noopener noreferrer"&gt;2.7" ePaper HAT&lt;/a&gt; because it was relatively cheap and offered plug and play compatibility. The version I bought is version B, which is the three-color black, white, and red display.&lt;/p&gt;

&lt;p&gt;The display is only $19.99 and was easy to install on my Raspberry Pi. It does have one big drawback, though. The refresh takes 15 seconds, which is a very long time. It also needs a full refresh between screens, so that is 15 seconds every time the image changes in any way. Waveshare also offers a black and white version for the same price that takes 6 seconds to refresh.&lt;/p&gt;

&lt;h2&gt;
  
  
  Initial setup
&lt;/h2&gt;

&lt;p&gt;Installing the display is very straight forward. Just line up the female header (black lego-looking thing) on the HAT with the male header (black spiky-looking thing) on the RPi. I find the easiest way to get it to connect is to pushed down on the two white circles with my thumbs once it is lined up. It should slide right on. No additional connections are required. The HAT comes with an SPI interface, but this is only needed if you are not connecting using the GPIO header.&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%2Fbkx2lyk56qy0c2a6lk0r.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%2Fbkx2lyk56qy0c2a6lk0r.png" alt="On the left, the eInk HAT showing the female header. On the right, the Raspberry Pi showing the male header."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Waveshare has also provided schematics, example code, and libraries for working with the display. All of this can be found in the &lt;a href="https://www.waveshare.com/wiki/2.7inch_e-Paper_HAT_(B)" rel="noopener noreferrer"&gt;wiki&lt;/a&gt;. It's important to note that the drivers and libraries are different for each display. The code in the wiki above only works with the 2.7" 3-color display. If you are working with a different display, the code will be similar but not the same.&lt;/p&gt;

&lt;h2&gt;
  
  
  Drawing to the screen
&lt;/h2&gt;

&lt;p&gt;To get started, make sure you are connected to your Raspberry Pi, either directly connected with keyboard, mouse, and monitor or remoting into the RPi using VNC (or similar service). The ePaper display does not interfere with the regular HDMI input, so you can connect a monitor to it while working with the ePaper display without any issues.&lt;/p&gt;

&lt;p&gt;You may also need to install the libraries below if they are not already on your Pi (they probably are).&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

sudo apt-get install python3-rpi.gpio python-imaging python-smbus python-dev


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

&lt;/div&gt;
&lt;p&gt;Create a folder for your ePaper projects. I put mine in &lt;code&gt;~/pi/epaper/&lt;/code&gt;, but you can put yours anywhere you want. Waveshare provides library files in C, python2, and python3. For this project, I am working with python3. You will need two files from the example code provided by Waveshare for any projects you do; they are &lt;code&gt;epd2in7b.py&lt;/code&gt; and &lt;code&gt;epdconfig.py&lt;/code&gt;. We will call these the drivers.&lt;/p&gt;

&lt;p&gt;You can put a copy of the drivers in every project you make, or you can put them into a dedicated folder and import them into your project from there. I chose the latter. This was my first python project, so it took me a minute to figure out how to make that work, but it's actually pretty simple:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create a folder in your project directory called &lt;code&gt;lib&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Place copies of both files into that folder&lt;/li&gt;
&lt;li&gt;In any project file that needs the drivers, import &lt;code&gt;sys&lt;/code&gt; and then append the lib folder to &lt;code&gt;sys&lt;/code&gt; so python knows where to find it. (Example code below)&lt;/li&gt;
&lt;li&gt;Import &lt;code&gt;epd2in7b&lt;/code&gt; into the project file. You do not need to import &lt;code&gt;epdconfig&lt;/code&gt;, as this is imported into &lt;code&gt;epd2in7b&lt;/code&gt; already.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;
&lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;insert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;./lib&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# Adds lib folder in this directory to sys
&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;epd2in7b&lt;/span&gt;


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

&lt;/div&gt;
&lt;p&gt;To draw an image to the screen, we also need &lt;code&gt;Image&lt;/code&gt;, &lt;code&gt;ImageDraw&lt;/code&gt;, and &lt;code&gt;ImageFont&lt;/code&gt; from the Python Image Library (PIL).&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;

&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;PIL&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Image&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ImageDraw&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ImageFont&lt;/span&gt;


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

&lt;/div&gt;
&lt;p&gt;Before we can work with the display, we need to create a variable for it and initialize the display. We also want to clear it before doing anything else. With the 2.7" display, we need to pass a color in hex to the &lt;code&gt;Clear&lt;/code&gt; function. Even though &lt;code&gt;Clear&lt;/code&gt; requires a color, I have not seen any difference from passing in different values, so just stick with &lt;code&gt;0xFF&lt;/code&gt;.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;

&lt;span class="n"&gt;epd&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;epd2in7b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;EPD&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;# get the display
&lt;/span&gt;&lt;span class="n"&gt;epd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;init&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;           &lt;span class="c1"&gt;# initialize the display
&lt;/span&gt;&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Clear...&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;    &lt;span class="c1"&gt;# prints to console, not the display, for debugging
&lt;/span&gt;&lt;span class="n"&gt;epd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Clear&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mh"&gt;0xFF&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;      &lt;span class="c1"&gt;# clear the display
&lt;/span&gt;

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

&lt;/div&gt;
&lt;p&gt;This is now a fully functioning program! If you run it, you should see the display turn black and then flash several times before clearing to "white," which is actually a greyish color similar to a book page.&lt;/p&gt;

&lt;p&gt;To print to the display, we are going to create a function that accepts a string.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;printToDisplay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;


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

&lt;/div&gt;
&lt;p&gt;This version of the display has both red and black pixels. Each color is rendered as a separate layer, the black is rendered first and then the red. When we create anything on the red layer, we still use &lt;em&gt;black and white&lt;/em&gt; for our colors on that layer, but it will render the black pixels in red.&lt;/p&gt;

&lt;p&gt;We have to create a separate image for red and black, even if we are only printing in one color. To do this, for each color we call &lt;code&gt;Image.new()&lt;/code&gt; and pass in the height and width of the display and a color to use for the display, which in this case is 255 (white).&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;

    &lt;span class="n"&gt;HBlackImage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Image&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;1&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;epd2in7b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;EPD_HEIGHT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;epd2in7b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;EPD_WIDTH&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="mi"&gt;255&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;HRedImage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Image&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;1&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;epd2in7b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;EPD_HEIGHT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;epd2in7b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;EPD_WIDTH&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="mi"&gt;255&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


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

&lt;/div&gt;
&lt;p&gt;Passing in the height first, and then the width, for the display dimensions, as above, will cause the text to display horizontally. To display  the text vertically just swap the heights and widths in the above statements.&lt;/p&gt;

&lt;p&gt;For this demo we are just printing text to the screen. We first need to get a draw object and then set our font. We will only be drawing to the black layer. The red layer will stay blank.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;

    &lt;span class="n"&gt;draw&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ImageDraw&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Draw&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;HBlackImage&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# Create draw object and pass in the image layer we want to work with (HBlackImage)
&lt;/span&gt;    &lt;span class="n"&gt;font&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ImageFont&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;truetype&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;/usr/share/fonts/truetype/google/Bangers-Regular.ttf&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# Create our font, passing in the font file and font size
&lt;/span&gt;

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

&lt;/div&gt;
&lt;p&gt;The Bangers font is from &lt;a href="https://fonts.google.com/" rel="noopener noreferrer"&gt;Google Fonts&lt;/a&gt;. If you don't have this font and don't want to install it, you can use any other font you like.&lt;/p&gt;

&lt;p&gt;Once we create the draw and font objects, we can use them to create our text. The first argument is the starting position of the text in pixels, then the string, the font, and the fill.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;

   &lt;span class="n"&gt;draw&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;text&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="mi"&gt;25&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;65&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;font&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;font&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;fill&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;We need to add our images to the screen. We use &lt;code&gt;display()&lt;/code&gt; and &lt;code&gt;getbuffer()&lt;/code&gt; from the &lt;code&gt;epd2in7b&lt;/code&gt; drivers to do this.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;

    &lt;span class="n"&gt;epd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;display&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;epd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getbuffer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;HBlackImage&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;epd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getbuffer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;HRedImage&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;


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

&lt;/div&gt;
&lt;p&gt;Even though we didn't do anything with the red layer, we still have to pass it to the &lt;code&gt;display()&lt;/code&gt; function.&lt;/p&gt;

&lt;p&gt;Finally, to see what we have done, we need to invoke our &lt;code&gt;printToDisplay()&lt;/code&gt; function.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;

&lt;span class="nf"&gt;printToDisplay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Hello, World!&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


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

&lt;/div&gt;
&lt;p&gt;Now save and run the program. It will clear the screen first, then after a couple of seconds the screen will start flashing again to place the text. If you watch your console, you will see that the screen remains busy a few seconds after it is cleared. Once the screen is released, the text starts to render. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://gist.github.com/RaneWallin/3d8645d06aed9251eed8c9079314807f" rel="noopener noreferrer"&gt;Here is a link to this complete program&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Awesome! You can write to your display. But what about those buttons? Let's talk about that.&lt;/p&gt;
&lt;h2&gt;
  
  
  Accessing the buttons
&lt;/h2&gt;

&lt;p&gt;For this part of the project we will use the &lt;code&gt;gpiozero&lt;/code&gt; library provided by RaspberryPi.org to access our buttons and use them to interact with the program. Start by importing the Button module from the &lt;code&gt;gpiozero&lt;/code&gt; library. &lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;

&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;gpiozero&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Button&lt;/span&gt;


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

&lt;/div&gt;
&lt;p&gt;The trickiest part about working with the buttons is figuring out which pin goes with which button. Waveshare offers a &lt;a href="https://www.waveshare.com/wiki/File:2.7inch_e-Paper_HAT_Schematic.pdf" rel="noopener noreferrer"&gt;schematic&lt;/a&gt;. Since this was my first time working with RPi, python, and schematics, it took me a bit of time to work out what it was telling me. I'll save you some trouble and tell you right now, the corresponding pins, from top to bottom are 5, 6, 13, 19. &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%2Faltsbd45hhbgg7ms3o1p.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%2Faltsbd45hhbgg7ms3o1p.png" alt="Buttons on the 2.7"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To use the button, first assign it to a variable. You can use the &lt;code&gt;Button()&lt;/code&gt; function imported from &lt;code&gt;gpiozero&lt;/code&gt; and pass in the pin number from above. For this demo, we are only working with the first button, at pin 5.This assignment will be near the top of the file right below the imports.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;

    &lt;span class="n"&gt;btn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Button&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# Assign btn to the button on the HAT at pin 5
&lt;/span&gt;

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

&lt;/div&gt;
&lt;p&gt;To perform an action when the button is pressed, we will assign a function to the when_pressed property on the button. This should happen at the bottom of the file.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;

&lt;span class="n"&gt;btn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;when_pressed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;handleBtnPress&lt;/span&gt;


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

&lt;/div&gt;
&lt;p&gt;Now we need to make our &lt;code&gt;handleBtnPress()&lt;/code&gt; function. We will do this directly above the previous assignment and we will move the line where we invoked &lt;code&gt;printToDisplay()&lt;/code&gt; into that function.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;handleBtnPress&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="nf"&gt;printToDisplay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Hello, World!&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


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

&lt;/div&gt;
&lt;p&gt;To test your program, run it and wait for the console to show that the display is not busy. It will show the message &lt;code&gt;e-paper busy release&lt;/code&gt;. Once that is done, press the first button. If everything is correct, it should update to display "Hello, World!"&lt;/p&gt;

&lt;p&gt;&lt;a href="https://gist.github.com/RaneWallin/339e3644018d11ef9d6e33960059c433" rel="noopener noreferrer"&gt;A complete version of the updated program is here&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Putting it all together
&lt;/h2&gt;

&lt;p&gt;Now you can print to the display and use a button to cause the display to update. But, there are four buttons! /picard&lt;/p&gt;

&lt;p&gt;If you want each button to do a different thing, you have some options. You can create functions for each button and assign those functions to when_pressed as above or you could even have a single function that changes the behavior depending on which button is pressed. To do this, look for the pin number of the button and use a &lt;code&gt;switcher&lt;/code&gt; to decide what to do. The &lt;code&gt;when_pressed&lt;/code&gt; function passes the button as an argument automatically. To get the pin number, you need to access &lt;code&gt;btn.pin.number&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;&lt;em&gt;Don't forget, you need to wait for the display to release before pressing the next button.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;See the example below.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;

&lt;span class="n"&gt;btn1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Button&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;btn2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Button&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;btn3&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Button&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;13&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;btn4&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Button&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;19&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;handleBtnPress&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;btn&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;pinNum&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;btn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;number&lt;/span&gt;
    &lt;span class="n"&gt;switcher&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Hello, World!&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;This is my first &lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;RPi project.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="mi"&gt;13&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Hope you lik it.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="mi"&gt;19&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Goodbye!&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;msg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;switcher&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pinNum&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Error&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;printToDisplay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;btn1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;when_pressed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;handleBtnPress&lt;/span&gt;
&lt;span class="n"&gt;btn2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;when_pressed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;handleBtnPress&lt;/span&gt;
&lt;span class="n"&gt;btn3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;when_pressed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;handleBtnPress&lt;/span&gt;
&lt;span class="n"&gt;btn4&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;when_pressed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;handleBtnPress&lt;/span&gt;


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

&lt;/div&gt;
&lt;p&gt;&lt;a href="https://gist.github.com/RaneWallin/fd73ddbffdabea23358f722adb9f4075" rel="noopener noreferrer"&gt;The complete code for the multi-button project is here&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;This was my first Raspberry Pi project and my first time working with python. It was a lot of fun, but it was also hard to find resources for working with the ePaper display. Even though Waveshare has a lot of information, they don't have any tutorials or real documentation around working with the display.&lt;/p&gt;

&lt;p&gt;The long refresh time matters a lot. It's fun to play with, but it would be too frustrating to use for any real projects. After some extra research, I believe that &lt;a href="https://www.waveshare.com/2.9inch-e-Paper-HAT-D.htm" rel="noopener noreferrer"&gt;2.9" flexible eInk HAT&lt;/a&gt; from Waveshare would have been a better option. It is a 2-color display and has a refresh time of 2 seconds. This one is only a few dollars more at $23.99. For a more production-ready version, the &lt;a href="https://www.waveshare.com/6inch-e-Paper-HAT.htm" rel="noopener noreferrer"&gt;800x600 6" display&lt;/a&gt; has a refresh time of less than 1 second, but is a bit more pricey at $74.99.&lt;/p&gt;


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



</description>
      <category>raspberrypi</category>
      <category>eink</category>
      <category>python</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>When school and work collide: Surviving the perfect storm</title>
      <dc:creator>Rane Wallin</dc:creator>
      <pubDate>Tue, 23 Jul 2019 20:28:42 +0000</pubDate>
      <link>https://dev.to/ranewallin/when-school-and-work-collide-surviving-the-perfect-storm-3g42</link>
      <guid>https://dev.to/ranewallin/when-school-and-work-collide-surviving-the-perfect-storm-3g42</guid>
      <description>&lt;p&gt;July 8 marked an exciting day for me. After complete Lambda School's Full Stack Web curriculum, I started my third and final build week. For those not familiar with Lambda School, the core curriculum is broken into 3 - 5 sections with a build week at the end of each section. During the build week, you work with students in all sections toward to the goal of completing a full, production-ready project. It's a great opportunity to reinforce mastery, work in a team, and build something to add to your portfolio. &lt;/p&gt;

&lt;p&gt;In the part time program our build "week" is actually two weeks. Ideally, we restrict our build time to the same class schedule that we hold for lectures, though it doesn't always work out that way. As the final hours approach it is not uncommon to sacrifice at least one weekend day to polishing and refining your code.&lt;/p&gt;

&lt;p&gt;Like most part time students, and probably many full time students, I have a full time job. I work for Nordstrom in a hybrid tech support/help desk position. I work directly with customers facing technical challenges, I open tickets to other departments, escalate problems, and work directly with those departments to find the best solutions for our customers. Our team also supports our contact center employees with system issues in the same manner.&lt;/p&gt;

&lt;p&gt;Working and going to school is never easy, but as this build week approached, it lined up with another big, important, and time consuming event in my life Nordstrom's annual Anniversary sale. For Nordstrom, this sale is as big as the Holiday season, if not bigger. During the first hours of the sale we move millions of dollars of merchandise &lt;em&gt;every minute&lt;/em&gt;. With so much traffic, there are bound to be challenges that our customers face, and that's where my team comes in.&lt;/p&gt;

&lt;p&gt;Our small team of 10 people is on the front line when it comes to supporting our customers when these issues arrive. As such, big events like Anniversary and Holiday require extra dedication and time; and, by that, I mean ample overtime.&lt;/p&gt;

&lt;p&gt;Build week started July 8th, Anniversary started July 12th. Two big, exciting, and stressful events colliding at just the right time to create a perfect storm. All of this made even more challenging by the fact that I start work at 3:00 AM and have my Lambda class until 9:00 PM Monday - Friday. &lt;/p&gt;




&lt;p&gt;Nordstrom is an awesome and supportive company, and our customers are truly the best. I've worked in customer service for more than 10 years, and I've never worked with better customers than our Nordstrom customers. But, no matter how great the customers and the company, customer service is mentally and emotionally exhausting. Talking to people for 10 - 12 hours straight can wear down the most resilient people. Finishing a 12 hour day talking non-stop to customers and then finding the emotional fortitude to say "okay, let's get to back to work on this project" is a greater challenge than one might image. &lt;/p&gt;

&lt;p&gt;It wasn't enough to survive, I needed to thrive. I needed to build an amazing project to ensure I would have something great to add to my portfolio, and I needed to kill it at work, because that's what I'm there to do. I've been with Nordstrom for 5 years and there's no slowing down now! Getting through it all required developing some strategies.&lt;/p&gt;

&lt;h2&gt;
  
  
  Get outside
&lt;/h2&gt;

&lt;p&gt;Since I work from home and my classes are all online, it's easy to stay in the house all day, but it's not wise. I've fallen into that trap before and it leads only to depression and fatigue. &lt;/p&gt;

&lt;p&gt;Being in Arizona, where it's been 105° - 115° F during the past two weeks, added an additional layer of difficulty. I needed to find ways to get out early or late. Fortunately, I have an awesome and understanding boss. Since I start work at 3 AM getting out before work is pretty much impossible, but my boss arranged for me to get an hour for lunch early in the day. During which time, I could go out for walks or quick bike rides. The sunshine and fresh air made a huge difference.&lt;/p&gt;

&lt;h2&gt;
  
  
  Do it for the team
&lt;/h2&gt;

&lt;p&gt;It can be easy to get focused on your own needs and challenges, but whether at work or during build week, I was always working with a team. Focusing on the team's needs gave me extra motivation to keep pushing through. &lt;/p&gt;

&lt;p&gt;At work, if I'm late, slow, or unprepared it would impact my team and my customers. Likewise, for build week, the backend I built needed to support the frontend developers. If I didn't complete my milestones in a timely manner, it would get them off track, as well. Keeping these things in mind helped me stay motivated when all I wanted to do was take a nap.&lt;/p&gt;

&lt;h2&gt;
  
  
  Take a nap
&lt;/h2&gt;

&lt;p&gt;Okay, I know what I just said, but, at the same time, I needed to be alert and mentally strong whether working with customers or working with my build week team. Working 19-hour days gets absolutely exhausting, I know, I've been doing it for months even before now. Sometimes you just need to take care of yourself or you won't be any use to your teammates. A couple of days, when I knew my milestones were met, I took the time to take short naps before getting back to the build week schedule.&lt;/p&gt;

&lt;h2&gt;
  
  
  Do it for yourself
&lt;/h2&gt;

&lt;p&gt;Anyone who is working and going to school is doing it because they imagine a better, more satisfying life for themselves (and their families). When it gets overwhelming, it's important to remember that. Focus less on how hard it is now and more on how much better it will be when it's done. I want nothing more in my life right now than to transition into a full time developer role. Meeting these challenges is just one more part of meeting that goal.&lt;/p&gt;




&lt;p&gt;In the end, I kicked build week's butt. I created an amazing backend server that I am proud of and thrilled to add to my portfolio. I also kept up with the demands of work and banked a load of overtime, which is always nice to see on the paycheck!&lt;/p&gt;

</description>
      <category>school</category>
      <category>work</category>
      <category>productivity</category>
      <category>javascript</category>
    </item>
  </channel>
</rss>
