<?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: jakedapper</title>
    <description>The latest articles on Forem by jakedapper (@jakedapper).</description>
    <link>https://forem.com/jakedapper</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%2F894021%2Fcd85af82-1e49-4e78-bfb7-a9a8f3f48941.png</url>
      <title>Forem: jakedapper</title>
      <link>https://forem.com/jakedapper</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/jakedapper"/>
    <language>en</language>
    <item>
      <title>Setlistopedia</title>
      <dc:creator>jakedapper</dc:creator>
      <pubDate>Fri, 07 Jun 2024 01:06:15 +0000</pubDate>
      <link>https://forem.com/jakedapper/setlistopedia-3mge</link>
      <guid>https://forem.com/jakedapper/setlistopedia-3mge</guid>
      <description>&lt;p&gt;Not the best name but a fun project nevertheless.&lt;/p&gt;

&lt;p&gt;A few months ago I interviewed for a job where I was assessed on my knowledge of Node.js. At the time, it was very close to nothing. To prevent this from happening again, I decided to learn it. Around the same time I started listening to the Grateful Dead a lot. While listening to the Grateful Dead, I noticed some patterns in their setlists.  I enjoyed hearing how one song would flow into the next across many different shows. Curious if there were more of these patterns in their setlist sequencing, and wanting to learn Node.js, I decided to build a web application which analyzed a band’s setlists. I utilized React, Typescript, Node.js, and Prisma as an ORM for a PostgreSQL database. Computations performed on an artist’s data included the top five songs they ever played, what year they played a particular song the most, and which song is most likely to be played before or after.&lt;/p&gt;

&lt;p&gt;While certain parts were easy to ascertain a path to implementation, certain parts were frustratingly difficult. But only some. For instance, I wrote an iterative function which creates a frequency counter for each unique song in a collection of an artist’s setlists. This was easy. But getting comfortable with typescript and the plethora of syntax that follows? That was particularly difficult. &lt;/p&gt;

&lt;p&gt;I eventually came around to enjoy the benefits of typescript - I found I could code more efficiently, interacting with pre-defined data structures safely and efficiently.  Since my application’s main utility is analyzing data structures, the benefits shone through quickly, however frustrating typescript/eslint’s incessant complaints were. As with most things, it just took some practice. &lt;/p&gt;

&lt;p&gt;In order to create statistics on a band’s live performances I needed data to analyze. I knew there was a thorough data source of setlists on a website called SetlistFm. Luckily, they have an API available. I designed the app to allow users to search for an artist they were interested in. When a user searches for an artist, a check on whether said artist is in the database occurs. If the artist was not in the database a series of requests would be sent to SetlistFm.com until all pages of data were ingested and added to the database. The idea was that over time, with more user activity, the database would become more comprehensive and the reliance upon SetlistFm’s API would decrease. &lt;/p&gt;

&lt;p&gt;This would have been fine, however, there is a rate limit for requests made to their API. I realized this would cause a decent amount of trouble for my application. It would only take a small number of users to make simultaneous requests to cause 429 response errors to be sent. Initially, after some Google searches and StackOverflow exploration, I thought implementing a retry function with exponential backoff might save a user from these errors.  But with the possibility of more and more users making requests, this would still not suffice. I thought about it like water flowing through a pipe with holes in the top of it - at a slow flow rate, all of the water would pass through fine and make it to its destination, but with too much water flowing through the pipe, you’re going to have a mess. As an alternative, I decided to seed my database with a lot of artists’ data using SetlistFm’s API. This would significantly uncouple any reliance upon SetlistFm’s API. &lt;/p&gt;

&lt;p&gt;I learned a lot but below I’ve listed some of the things I found to be most interesting. &lt;/p&gt;

&lt;p&gt;I learned about utilizing local storage to persist state on a refresh.&lt;br&gt;
I learned about organizing code more efficiently and how to better follow DRY principles. For example, writing basic helper functions and services.&lt;br&gt;
I learned about Domain Driven Design and the importance of naming variables.&lt;br&gt;
I learned how to troubleshoot, debug, and measure efficiency better through a myriad of console.logs and even inspecting memory usage in devTools.&lt;br&gt;
I learned about database architecture and how to be strategic in creating only the tables you need with only the fields you need - the same goes for querying said database.&lt;br&gt;
I learned about creating dynamic URLs which send pertinent information from the client to the server.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Asynchronous Behavior Got You Down?</title>
      <dc:creator>jakedapper</dc:creator>
      <pubDate>Fri, 28 Oct 2022 23:01:03 +0000</pubDate>
      <link>https://forem.com/jakedapper/asynchronous-behavior-got-you-down-2fkb</link>
      <guid>https://forem.com/jakedapper/asynchronous-behavior-got-you-down-2fkb</guid>
      <description>&lt;p&gt;This a specific sort of problem with a specific sort of solution. So far, so vague.&lt;/p&gt;

&lt;p&gt;In Javascript/React we often run into asynchronous behavior - that is, certain parts of our code run before others. This could be due to a number of reasons, such as a lag in the code running and &lt;em&gt;state&lt;/em&gt; being set and the nature of &lt;em&gt;fetch requests&lt;/em&gt;/&lt;em&gt;promises&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;There's ways we can handle this. &lt;/p&gt;

&lt;p&gt;One way is to use the useEffect hook. Whatever code is contained within the useEffect hook will run upon page render AND when a change is made to whatever is in the dependency array.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Q3e90Oj9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5ysmmcbe6yt1riagrbso.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Q3e90Oj9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5ysmmcbe6yt1riagrbso.png" alt="Image description" width="494" height="156"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This can be utilized very powerfully. The primary instance I have run into is when some user action happens and triggers a POST or PATCH request, the data displayed on the frontend may need to be updated. If we put the state, where we stored our data, in the dependency array, it will get triggered and run again, thus populating our frontend with new, updated data.&lt;/p&gt;

&lt;p&gt;But sometimes, even still, there is a lag in the setting of our state(s) (which is storing some of our data and being used to display it on the frontend) on being set and the code running. This can be bad. For example, if we want to map over our state, which should be an array of data, but it's not yet set to said array, the app is going to stop working. It will error out and say, something like, "restaurants.map is Undefined." which, in English, means, "We can't map over that! It's not an array!" And it's not, at least not for another second or two.&lt;/p&gt;

&lt;p&gt;Even with useEffect, this async behavior can be a bummer. &lt;br&gt;
While it wasn't the "most correct" or "efficient" move, I even have used setTimeOut() to account for the latency of state being set.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--fSegUHIj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/llbgugryrr4098vmwl27.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--fSegUHIj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/llbgugryrr4098vmwl27.png" alt="Image description" width="880" height="340"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here, I'm using the .find() method, which does the same sort of thing as .map(), iterates through an array, and would return the same aforementioned error if its object is, indeed, not an array. The setTimout() is an asynchronous function, so it's kind of like fighting fire with fire. Its first argument is the code you want to run and its second argument is the number of milliseconds you want it to wait to execute upon page render. &lt;/p&gt;

&lt;p&gt;The other example I would like to share is one which uses a styled component from MaterialUi's library, CircularProgress. MaterialUi Docs are mostly great and provide a clear walkthrough if you are interested in implementing some built-in styles to you React project. CircularProgress is a loading circle, more or less. &lt;/p&gt;

&lt;p&gt;In my example, "user" is a state that we need for the rest of the code to run, but if we don't have a user yet, due to whatever reason, another error or simply asynchronous behavior, hopefully the latter, because if it is, this might help.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--WyguxNDO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hspyb0nnye10iomz9o4v.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--WyguxNDO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hspyb0nnye10iomz9o4v.png" alt="Image description" width="464" height="144"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here, we are using conditional logic. If we don't yet have a truthy-valued "user" state, we will get a loading icon returned. Then, when there is a user, the rest of the code will run!&lt;/p&gt;

&lt;p&gt;State can be tricky and you may still run into issues.&lt;/p&gt;

&lt;p&gt;Another, but more complex, tool to use is a newer part of React, async/await. This involves creating an "async function" rather than a regular ole "function". I'm not going to go into it because that's a blog post all on it's own.  &lt;/p&gt;

</description>
    </item>
    <item>
      <title>Cookies vs. Sessions</title>
      <dc:creator>jakedapper</dc:creator>
      <pubDate>Wed, 12 Oct 2022 01:43:34 +0000</pubDate>
      <link>https://forem.com/jakedapper/cookies-vs-sessions-556k</link>
      <guid>https://forem.com/jakedapper/cookies-vs-sessions-556k</guid>
      <description>&lt;p&gt;I write this blog as I enter the final phase of my software engineering program through Flatiron School. The latest tool added to our arsenal basically allows users the ability to log-in and out, amongst some other things. What are these tools? Cookies and Sessions.&lt;/p&gt;

&lt;p&gt;You may have questions like I did. I had heard of cookies, but was largely unfamiliar with sessions.&lt;/p&gt;

&lt;p&gt;What’s the difference? How are they even really used? &lt;/p&gt;

&lt;p&gt;Cookies can get a bad rap. Understandably so, as they are pieces of information sent along with requests to the server. Some of this information storage is used in pretty helpful ways, like what’s in your shopping cart , user preferences, and track items previously viewed (on webstores, etc).&lt;/p&gt;

&lt;p&gt;Cookies are stored locally, in the browser, and on the server, whereas sessions are only stored on the browser.&lt;/p&gt;

&lt;p&gt;Sessions are cookies who don’t want to be seen in their pure, true form. They like disguises. At least when we use Rails to disguise them. This allows them to not be tampered with.&lt;/p&gt;

&lt;p&gt;Sessions are deleted when the session ends, aka the browser/tab is closed, whereas cookies persist - they have been stored on the local storage of your computer.&lt;/p&gt;

&lt;p&gt;Occasionally, sites will use third-party cookies. These are data collectors sending information to other domains, aka different from the website the user is currently using. This is usually simple advertisement-oriented data collection of user behavior, i.e. which ads they clicked on, what items they favorited, etc.&lt;/p&gt;

&lt;p&gt;We learned how to implement cookies/sessions in simple web-apps built on Ruby/Rails and React. The basic configuration involves adding some code to the application’s config file.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--iUatEpVs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/619eh6jb4mot1wiho2ki.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--iUatEpVs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/619eh6jb4mot1wiho2ki.png" alt="Image description" width="499" height="207"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next we add this code to our ApplicationController.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--qle-PFzu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ipe467vp0grwsh3mim7z.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--qle-PFzu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ipe467vp0grwsh3mim7z.png" alt="Image description" width="256" height="26"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;From here, we are essentially utilizing a SessionsController to implement Create and Destroy actions for users - that is, upon “logging in”, aka filling out a form which, when submitted, sends a POST request to our server’s sessions endpoint, will create a session (if authenticated, but we’ll circle back to that in a moment). With a session successfully created, the user is basically logged in. The same CRUD request logic  follows for logging out - that is, the user clicking the “Log Out” button sends a DELETE request to the server’s sessions endpoint.&lt;/p&gt;

&lt;p&gt;Create Action on the sessions’ server that happens upon the POST request.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--kU-BwPQJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xiolmnkgxutif5jaq7fp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--kU-BwPQJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xiolmnkgxutif5jaq7fp.png" alt="Image description" width="697" height="166"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Destroy Action on the sessions’ server that happens upon the Delete request.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--OUtABIcl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8902oc2np17if4sqp32m.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--OUtABIcl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8902oc2np17if4sqp32m.png" alt="Image description" width="242" height="83"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There’s some extra code in the create action which helps set up the ability to authenticate the user exists and they used proper log-in credentials.  It checks to see if the employee exists and if their password attribute matches the one entered in the form/sent with the POST request. If it does, a session associated with that user (employee) is created.&lt;/p&gt;

&lt;p&gt;However, it’s important to note, at the top of the SessionsController, be sure to include this line of code as well:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--uglPp_mm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/no2nnumh6p79j63jsdqy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--uglPp_mm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/no2nnumh6p79j63jsdqy.png" alt="Image description" width="327" height="23"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Additionally, include the following in the ApplicationController. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--SiODVAcf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/k9d275kc5tx6xaer6dfz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--SiODVAcf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/k9d275kc5tx6xaer6dfz.png" alt="Image description" width="880" height="235"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This allows the server to check if there is a user(employee).&lt;/p&gt;

&lt;p&gt;This process is crucial to maintain client-specific state across requests - aka everytime the webpage refreshes certain states, where user preferences, user-specific accessible data lives/is set (temporarily), resets to default. It’s like you never logged in at all.&lt;/p&gt;

&lt;p&gt;This can be avoided by including a show route in the user (employee) controller. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--KvcbVDt9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/v16yydyt6xxc0elewhu3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--KvcbVDt9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/v16yydyt6xxc0elewhu3.png" alt="Image description" width="338" height="68"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And this in routes:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--JhSw7K0n--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hphdn47xb6aa24nqkna9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--JhSw7K0n--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hphdn47xb6aa24nqkna9.png" alt="Image description" width="235" height="19"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And then this allows the frontend to know what the backend already knows. This GET request is resetting the current user state, that is, who is logged in and in store of the sessions (cookie) model.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--_ACa7AJT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2f2mx8bkrxawmy0p20s8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--_ACa7AJT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2f2mx8bkrxawmy0p20s8.png" alt="Image description" width="292" height="173"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Using State and useEffect To Dynamically Render Data</title>
      <dc:creator>jakedapper</dc:creator>
      <pubDate>Fri, 16 Sep 2022 16:34:35 +0000</pubDate>
      <link>https://forem.com/jakedapper/using-state-and-useeffect-to-dynamically-render-data-2f6j</link>
      <guid>https://forem.com/jakedapper/using-state-and-useeffect-to-dynamically-render-data-2f6j</guid>
      <description>&lt;p&gt;I am finishing the 9th week (out of 15) of the Flatiron School Software Engineering program. As our introduction to Ruby comes to a close, a classmate and I built a simple web app which allowed users to access a database of concerts or eateries based off which city they may be visiting. To do this we built a database with associations using Ruby, Active Record, and Sinatra and built a frontend UI using Javascript and React. &lt;/p&gt;

&lt;p&gt;One of my favorite aspects of our project is how we chose to render our data. We wanted to dynamically display data from two different tables/models. Needing a way for users to differentiate which data they would see, we created nav-bar and two buttons.  &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Dk6G57lI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nnvb2kidcx0ph651ji4z.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Dk6G57lI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nnvb2kidcx0ph651ji4z.png" alt="Image description" width="880" height="163"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Clicking on a nav-bar link or button sets a state (attractionType) to a particular value. This value would represent a corresponding endpoint to the desired data. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--QIickOx3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/czj8mclzyym6p1sndw6f.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--QIickOx3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/czj8mclzyym6p1sndw6f.png" alt="Image description" width="227" height="74"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The nav-bar links were given values which correspond to the desired data's respective endpoint.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--hhJIM97b--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/l9uzstzj8avdpbjkusuh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--hhJIM97b--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/l9uzstzj8avdpbjkusuh.png" alt="Image description" width="770" height="133"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This was made possible by how we set up the controllers in our backend in Ruby/Active Record/Sinatra.  Below are a couple GET requests with endpoints, 'concerts' or  'eateries'.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--5OMfFnjo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8dpegjvrdt0ygfrdtung.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--5OMfFnjo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8dpegjvrdt0ygfrdtung.png" alt="Image description" width="200" height="90"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--V1Crqho0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vptne1yq94cuotr2sumw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--V1Crqho0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vptne1yq94cuotr2sumw.png" alt="Image description" width="271" height="86"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The interpolated variable, the state known as "attractionType", is a dynamic endpoint. It changes based off user action. Thus, we can access different data as this variable's value changes. &lt;/p&gt;

&lt;p&gt;Using useEffect effectively is another crucial step in this process. It allows the web app to operate dynamically and accurately. Anytime the second argument of useEffect changes, the useEffect runs. Passing this "slice of state"(attractionType) as the second argument of our useEffect asks the body of the useEffect to rerun whenever the second argument/state changes. When the state changes, a new GET/fetch request is sent and different display data is set.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--CAHJeZgZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/u7zpa090omj0fliojz39.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--CAHJeZgZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/u7zpa090omj0fliojz39.png" alt="Image description" width="453" height="98"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Conditional rendering is powerful. In our web app a state (attractionType) not only functionally determines which set of data is rendered, but also which corresponding component is rendered.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--0urx1vt5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/obckjfkmtidj7m0hj5mi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--0urx1vt5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/obckjfkmtidj7m0hj5mi.png" alt="Image description" width="589" height="237"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We even utilized it for other front-end purposes, such as which Header would be displayed.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--eFZMbbdT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/omi3ne50ves9tish7bap.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--eFZMbbdT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/omi3ne50ves9tish7bap.png" alt="Image description" width="537" height="23"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Conditional rendering is common because it's useful and dynamic. There are many circumstances where we will need to render/access different data based on user actions, including, but not limited to, clicking a link. Utilizing state is a simple and singular solution to create dynamic endpoints. From these endpoints we can perform a myriad of CRUD actions. Simultaneously, using the same "slice of state", we are able to conditionally render the data and elements/components to the front-end.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>react</category>
      <category>ruby</category>
      <category>beginners</category>
    </item>
    <item>
      <title>How Many Fonts You Got?</title>
      <dc:creator>jakedapper</dc:creator>
      <pubDate>Fri, 26 Aug 2022 16:40:00 +0000</pubDate>
      <link>https://forem.com/jakedapper/how-many-fonts-you-got-5824</link>
      <guid>https://forem.com/jakedapper/how-many-fonts-you-got-5824</guid>
      <description>&lt;p&gt;We deal with limitations everyday. Everything from our computers to our cars have them, even ourselves. The goal is to accept them, ask for help when we need it, and adapt. While discovering yet another lovely limitation of the beloved language, 'CSS', I had to adapt - that is, learn.&lt;/p&gt;

&lt;p&gt;As a student in Flatiron School's Software Engineering program I'm learning a lot in a short span of time. We  are finishing up our second phase which was centered around React, a JavaScript library used to help build user interfaces. As we close this chapter in our journey, we are building our own web applications. After building out basic functionality we approached a point where it was necessary to start making things look nice - aka start coding (one of) the dreaded headache(s) of web development, CSS.&lt;/p&gt;

&lt;p&gt;CSS deserves more how-to's than I can count. This one will focus on something I am a little bit of a nerd about - the importance of fonts (and how CSS lacks in this department)! CSS has a number of preloaded fonts to use on your web app, but it doesn't have ones that are particularly fun, or kitschy, like a western-themed font. Our project/web app very much has a Mortal Kombat-esque theme, thus, an appropriately themed font was crucial. &lt;/p&gt;

&lt;p&gt;Just like everything else fonts have their own file type. In fact, this can be a few different file types. Some are for certain web-browsers, some just for desktop use. A lot of times you'll see 'TTF' types, especially on your local system. But, please note, a lot of web-browsers use 'WOFF' or 'WOFF2.' Thus, if we download a TTF, we probably need to change it to a 'WOFF/WOFF2' in order to utilize for our web-app.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--iHIXdHCH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/82evdg6zecpji5mcwqs5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--iHIXdHCH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/82evdg6zecpji5mcwqs5.png" alt="Mortal Kombat TTF Font Acquired at DaFont.com" width="807" height="650"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Luckily, people have been here before, needing a specific font that CSS does not have built in. So here's what you need to do to add your font:&lt;/p&gt;

&lt;p&gt;1) Identify which font you want to use and download it to your computer. &lt;/p&gt;

&lt;p&gt;2) If the font file ends in TTF, we need to convert it to a file-type recognized by most web-browsers, like 'WOFF'. (FontSquirrel will do this as seen below)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Err9VwPC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9vlna5lvnsmxik4l1ol1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Err9VwPC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9vlna5lvnsmxik4l1ol1.png" alt="FontSquirrel's Web Generator" width="786" height="514"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;3)When you have your correctly formatted font file, navigate to your code's css stylesheet. &lt;/p&gt;

&lt;p&gt;4) Make sure the css stylesheet has been linked to your application. We have a couple options. Our font can be stored and accessed locally or sent to whichever server we are using to host our application. I set mine locally by creating a folder in my './src' folder, where all of my code and css stylesheet live.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--rbjVLoct--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3wvs2da06ajbvkwvdmd7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--rbjVLoct--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3wvs2da06ajbvkwvdmd7.png" alt="Location of Fonts" width="162" height="265"&gt;&lt;/a&gt;&lt;br&gt;
Location of Fonts &lt;/p&gt;

&lt;p&gt;5) Next we need to add some instructions to our css stylesheet. We will use this generic format: &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--wnRvpsMt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wf55s2ve5j8sfwwlg5na.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--wnRvpsMt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wf55s2ve5j8sfwwlg5na.png" alt="Stylesheet template" width="509" height="132"&gt;&lt;/a&gt;&lt;br&gt;
Stylesheet Template&lt;/p&gt;

&lt;p&gt;&lt;em&gt;please note: name the font you are adding where this template says, "FontName", but make sure it's lowercase.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Here's an example of my code with the Mortal Kombat font:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--7ZQwaLuW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mot2e22blrl7b045l0md.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--7ZQwaLuW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mot2e22blrl7b045l0md.png" alt="Adding Mortal Kombat font to my stylesheet" width="475" height="123"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;6) Use the font the same way you would any other with the name you assigned.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s---JjP1ej2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wriz268tfn2dnttyxhlo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s---JjP1ej2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wriz268tfn2dnttyxhlo.png" alt="Image description" width="334" height="186"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This process is simple and adds a lot of flavor to your web apps. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--deEcL6cE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xmh8hevmfdzhqanyb6dr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--deEcL6cE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xmh8hevmfdzhqanyb6dr.png" alt="The Font Has Been Deployed!" width="880" height="794"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>css</category>
      <category>javascript</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Toggle Button</title>
      <dc:creator>jakedapper</dc:creator>
      <pubDate>Fri, 05 Aug 2022 18:42:25 +0000</pubDate>
      <link>https://forem.com/jakedapper/toggle-button-5ge1</link>
      <guid>https://forem.com/jakedapper/toggle-button-5ge1</guid>
      <description>&lt;p&gt;The process of learning javascript contains multitudes. There are peaks and there are valleys. It starts out simple. Then a wrench gets thrown into things and you start asking yourself the same questions again and again,  "Wait what goes where?",  "And that thing does what?",  "How do I make it do this?  Or that?" You learn how to ask better questions, too, largely due to necessity. All in all, there are concepts you just have to struggle with in order to fully grasp them. When you do, it's right as rain, easy as pie. &lt;/p&gt;

&lt;p&gt;Creating a "toggle button" is one of these frustrating tasks.&lt;br&gt;
I'm defining a "toggle button" here as an HTML element with an event listener attached to it, which, when clicked, can change an element AND change it back. For example, imagine Instagram. Now imagine there's a cool post you like. So you double tap the post and BOOM - it's been liked by you. The heart icon fills with color and the number of likes increases. If you double tap again, the same user action, the opposite event occurs, reverting the heart back to empty, and decreases the likes count to what it previously was. &lt;/p&gt;

&lt;p&gt;The first thing we need to do is identify what we want the "target" of our event to be - if you wanted something to happen when a user clicked a button, the button would be this "target". In my first example, the target element has been named "shinyBtn". When clicked, the display image of a Pokemon changes. When clicked again, it changes back. It toggles. But, how?&lt;/p&gt;

&lt;p&gt;In the code below, I've created variables, assigned their values to locations on the DOM/HTML. This will allow me to set values on these elements' properties in the next step, i.e. "textContent" for a header/title element or the "src" for an image element. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--a1rp0eKM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/r1q4t5bd333el6mhkp38.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--a1rp0eKM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/r1q4t5bd333el6mhkp38.png" alt='"Grabbing" Elements Off the DOM' width="880" height="232"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next, I constructed a function which accesses an API database of Pokemon, performs a GET request, and sets particular pieces of that data on particular DOM/HTML elements, ultimately creating a display Pokemon with an image, name, height, weight, and type. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--TiewUCVw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/58mqsauin9bih3f90ej7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--TiewUCVw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/58mqsauin9bih3f90ej7.png" alt="Display Pokemon Function" width="880" height="559"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now that we have a display Pokemon, I will add some functionality to the "shinyBtn" using an event listener. Event listeners take two parameters, an event type (in this case, "click") and a function to be invoked when this event occurs. The function argument here will change the display "default" image to a "shiny" image.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--QA8eZzAJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/j26x3xqitzc4ghm1ubgw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--QA8eZzAJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/j26x3xqitzc4ghm1ubgw.png" alt="Image description" width="738" height="134"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is cool. This works. But not as a "toggle". It only works once (per object/pokemon) and in one direction - reassigning the display image source from the "default" image to the "shiny" image. If I click the "shinyBtn" again, it doesn't change back. How do I get it to change back? Can I add another event listener to the "shinyBtn" and have this function perform the reverse and reassign the "shiny" image to the "default"?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--j_n0Vpq1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1uq5rnapi95a693xpvcp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--j_n0Vpq1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1uq5rnapi95a693xpvcp.png" alt="Image description" width="830" height="140"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It doesn't work. This is due to javascript running top-down, left to right. The first event listener takes precedence over the second. This button already does a job every time it's clicked. We need this function's behavior to be conditional. If the image is the "default", it should change to the "shiny" image upon the click event and vice versa. This is simple and can look like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--xG_h_OGp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/no4x287l5znywm1scuo0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--xG_h_OGp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/no4x287l5znywm1scuo0.png" alt="Image description" width="880" height="237"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The same logic was used in the same web app to change the image of the Pokemon listed on the left side of the screen. With a "mouseover" event added to each image, whenever the mouse moves over the image, an event will occur. The function argument in the event listener will change the target image source to the "back" image if it's currently the "front" image, and vice versa.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--XJfgFeiH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bg8zntpqe9dfskf8tgvu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--XJfgFeiH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bg8zntpqe9dfskf8tgvu.png" alt="Image description" width="880" height="298"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;While this last example isn't a "button", it is still toggle behavior. &lt;/p&gt;

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