<?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: Eric</title>
    <description>The latest articles on DEV Community by Eric (@eric_havey).</description>
    <link>https://dev.to/eric_havey</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%2F724522%2F12ba62e0-e570-4976-964e-8f93e1c7b8fa.jpg</url>
      <title>DEV Community: Eric</title>
      <link>https://dev.to/eric_havey</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/eric_havey"/>
    <language>en</language>
    <item>
      <title>The very basics of Active Record Validations</title>
      <dc:creator>Eric</dc:creator>
      <pubDate>Wed, 22 Jun 2022 19:38:52 +0000</pubDate>
      <link>https://dev.to/eric_havey/the-very-basics-of-active-record-validations-n17</link>
      <guid>https://dev.to/eric_havey/the-very-basics-of-active-record-validations-n17</guid>
      <description>&lt;p&gt;Active Record Validations are a feature of Active Record that gives us the ability to validate data, before it reaches our database. This has a few benefits, but most importantly, we can make sure our database doesn't have unwanted values that could break our application later on.&lt;/p&gt;

&lt;p&gt;This guide will attempt to explain how Active Record Validations work, using the Active Records Validations guide as a general reference.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why use validations?
&lt;/h2&gt;

&lt;p&gt;First of all, why should we use validations? As alluded to before, validations are vital for making sure that all the values in our database are exactly within our expectations.&lt;/p&gt;

&lt;p&gt;According to the Ruby on Rails guide:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Model-level validations are the best way to ensure that only valid data is saved into your database. They are database agnostic, cannot be bypassed by end users, and are convenient to test and maintain.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;For example, if our database has a column for phone numbers, we know (within reason) that there every number should by 10 digits long (including area code) and by made up of only digits (0-9). So, before creating a new phone number in our database, we should &lt;em&gt;validate&lt;/em&gt; it first. If it's invalid, we should reject it.&lt;/p&gt;

&lt;p&gt;By making sure our database is valid, we can prevent potential bugs down the line.&lt;/p&gt;




&lt;h2&gt;
  
  
  Validation Helpers
&lt;/h2&gt;

&lt;p&gt;Validation helpers are the meat of Active Record Validations. These are pre-defined helpers that provide a set of built-in validation rules. We define our validations directly in the model class. With just the built-in validation helpers, we should be able to handle most, if not all, of our necessary validations.&lt;/p&gt;

&lt;p&gt;Some of the most useful helpers include: presence, uniqueness, length, comparison, and format. The full list of built-in validation helpers can be found &lt;a href="https://guides.rubyonrails.org/active_record_validations.html#validation-helpers"&gt;&lt;strong&gt;here&lt;/strong&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;em&gt;presence&lt;/em&gt;
&lt;/h3&gt;

&lt;p&gt;Presence validates that the specified attribute(s) are not empty (nil or an empty string: ""). It is, by far, the simplest helper, as well as, one of the most common helpers.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;  &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Person&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationRecord&lt;/span&gt;
    &lt;span class="n"&gt;validates&lt;/span&gt; &lt;span class="ss"&gt;:name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:phone_number&lt;/span&gt; &lt;span class="ss"&gt;presence: &lt;/span&gt;&lt;span class="kp"&gt;true&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, Active Record won't allow us to create a new person unless there is a name and phone number present. Notice, by the way, that we define our validations directly in each model.&lt;/p&gt;

&lt;p&gt;Alternatively, the helper &lt;em&gt;absence&lt;/em&gt; does the opposite, ensuring that one or more attributes are absent before saving a new record.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;em&gt;uniqueness&lt;/em&gt;
&lt;/h3&gt;

&lt;p&gt;This helper ensures that each value of one or more attributes are unique. One of the most obvious use cases for this would be to ensure every created user had a unique email address.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;  &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationRecord&lt;/span&gt;
    &lt;span class="n"&gt;validates&lt;/span&gt; &lt;span class="ss"&gt;:email&lt;/span&gt; &lt;span class="ss"&gt;uniqueness: &lt;/span&gt;&lt;span class="kp"&gt;true&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;em&gt;length&lt;/em&gt;
&lt;/h3&gt;

&lt;p&gt;This helper is exactly what you think is; it validates the length of the attribute value. There are a few different options available with &lt;em&gt;length&lt;/em&gt;, to be as precise as you'd need to be. They are: &lt;em&gt;minimum&lt;/em&gt;, &lt;em&gt;maximum&lt;/em&gt;, &lt;em&gt;in&lt;/em&gt; (or &lt;em&gt;within&lt;/em&gt;), and &lt;em&gt;is&lt;/em&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;  &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Customer&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationRecord&lt;/span&gt;
    &lt;span class="n"&gt;validates&lt;/span&gt; &lt;span class="ss"&gt;:phone_number&lt;/span&gt; &lt;span class="ss"&gt;length: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;is: &lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For more info about the other options, visit the Ruby on Rails guide, &lt;a href="https://guides.rubyonrails.org/active_record_validations.html#length"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;em&gt;comparison&lt;/em&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;Comparison&lt;/em&gt; compares two values and will only validate if the comparison is true. Like &lt;em&gt;length&lt;/em&gt;, &lt;em&gt;comparison&lt;/em&gt; has several options to choose from. They are: :greater_than, :greater_than_or_equal_to, :less_than, :less_than_or_equal_to, :equal_to, and :other_than.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;  &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Employee&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationRecord&lt;/span&gt;
    &lt;span class="n"&gt;validates&lt;/span&gt; &lt;span class="ss"&gt;:hourly_wage&lt;/span&gt; &lt;span class="ss"&gt;comparison: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;greater_than_or_equal_to: :minimum_wage&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This examples validates that each employee's wage is never below minimum wage.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;em&gt;format&lt;/em&gt;
&lt;/h3&gt;

&lt;p&gt;The last validation helper in this blog is &lt;em&gt;format&lt;/em&gt;. Simply put, it validates that a attribute value matches a pre-defined regex pattern. This is useful for making sure an email address or a password follows a specific format.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;  &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationRecord&lt;/span&gt;
    &lt;span class="n"&gt;validates&lt;/span&gt; &lt;span class="ss"&gt;:email&lt;/span&gt; &lt;span class="ss"&gt;format: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;with: &lt;/span&gt;&lt;span class="sr"&gt;/^\w{2}\w*@\w+\.\w+$/&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;format&lt;/em&gt; basically allows you to be as flexible with your validations as regular expressions are. The only drawback is having to use regular expressions...&lt;/p&gt;




&lt;h2&gt;
  
  
  Conditional Validation
&lt;/h2&gt;

&lt;p&gt;To make our validations even more dynamic, Active Record gives us the option to run our validations based on specific conditions that we can define. To add conditions to your validations, simply tag on an &lt;code&gt;:if&lt;/code&gt; or an &lt;code&gt;:unless&lt;/code&gt;, with the name of a function that evaluates to true or false, in symbol format. I like the example code for custom validations in the Rails &lt;a href="https://guides.rubyonrails.org/active_record_validations.html#using-a-symbol-with-if-and-unless"&gt;docs&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;  &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Order&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationRecord&lt;/span&gt;
    &lt;span class="n"&gt;validates&lt;/span&gt; &lt;span class="ss"&gt;:card_number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;presence: &lt;/span&gt;&lt;span class="kp"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;if: :paid_with_card?&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;paid_with_card?&lt;/span&gt;
      &lt;span class="n"&gt;payment_type&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;"card"&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the example above, each payment has a "payment_type" associated with it. When using a credit card, we need to use the credit card number to process the payment. It would be wise to validate the credit card number before doing so, to ensure that only cc numbers in a specific format get processed, or else, the payment could fail and that is not ideal.&lt;/p&gt;

&lt;p&gt;Adding conditions to our validations greatly enhances our ability to write complex validations in a easy to read manner. With what we now have, we can setup just about any validation we can think of with the Rails built-in validation helpers. But, as an alternative to using the built-in helpers, we can define our own validation methods that will even do the few things the built-in helpers cannot.&lt;/p&gt;




&lt;h2&gt;
  
  
  Custom Validations
&lt;/h2&gt;

&lt;p&gt;Although the built-in validation helpers that Active Record gives us are awesome, we don't have to use them at all, and, in fact, won't always be enough for the type of validation we need. Instead, we can define our own custom validations to do any sort of validating we could possible desire. Custom validations are generally used for more complex validations while the built-in helpers are efficient for using more straight-forward validations, as their name's imply.&lt;/p&gt;

&lt;p&gt;Here's an example of a custom validator that fails if it's not the first of the month:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;  &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;DeliveryOrder&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationRecord&lt;/span&gt;
    &lt;span class="n"&gt;validate&lt;/span&gt; &lt;span class="ss"&gt;:promise_time_cannot_be_in_the_past&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;promise_time_cannot_be_in_the_past&lt;/span&gt;
      &lt;span class="n"&gt;errors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:promise_time&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"cannot be in the past"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;promise_time&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;today&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The example above is for a delivery order at a restaurant or whatever. There's no way the we could possibly promise to deliver anything that is before the order was placed. This validation ensures we won't have to deal with this later down the line.&lt;/p&gt;

&lt;p&gt;This could be written using the built-in validation helpers, but, for whatever reason, I decided I liked this better. Without having to understand the logic behind the validation, it's still obvious that this model is validating that the promise time cannot be in the past, as the name of the validation method eludes to. I guess it's up to preference for which way you'd like to use.&lt;/p&gt;




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

&lt;p&gt;In the article, I've only covered the absolute basics of Active Record Validations. The most glaring area I omitted was error handling. If you'd like to know more (and I encourage you to do so), please check out the main page on validations for Active Record &lt;a href="https://guides.rubyonrails.org/active_record_validations.html"&gt;here&lt;/a&gt;. The other bigger topic I didn't cover were the "Common Validation Options". They add a few additional ways to make your validations even more dynamic.&lt;/p&gt;

&lt;p&gt;Just like everything else in Rails, once your comfortable writing validations and don't need to flip back to the docs regularly, you can write very easy validations in only a few lines of code that are basically human readable. It's pretty incredible.&lt;/p&gt;




&lt;h2&gt;
  
  
  Resources &amp;amp; Acknowledgements
&lt;/h2&gt;

&lt;p&gt;This article basically cherry-picks and summarizes parts of the guide on Active Record Validations from the Ruby on Rails guides and can be found &lt;a href="https://guides.rubyonrails.org/active_record_validations.html"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Besides the Rails guides, these two YouTube tutorials were extremely helpful in understanding how validation worked in Rails:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=SaCGlchTxLI&amp;amp;t=173s"&gt;Ruby On Rails: Model Validations - Apple Juice Training&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=l-Jv5vMjB70&amp;amp;t=39s"&gt;Rails for Beginners Part 12: Validations - GoRails&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That's it. Thanks for reading. Go Twins!&lt;/p&gt;

</description>
      <category>ruby</category>
      <category>rails</category>
      <category>activerecord</category>
      <category>crud</category>
    </item>
    <item>
      <title>Associating Distant Table with Active Record</title>
      <dc:creator>Eric</dc:creator>
      <pubDate>Thu, 14 Apr 2022 18:02:52 +0000</pubDate>
      <link>https://dev.to/eric_havey/associating-distant-table-with-active-record-2957</link>
      <guid>https://dev.to/eric_havey/associating-distant-table-with-active-record-2957</guid>
      <description>&lt;p&gt;With Active Record, database tables can be connected together through Active Record association, allowing us to easily work with our database. Consider the diagram below:&lt;/p&gt;

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

&lt;p&gt;By creating different associations between these tables, Active Record will give our models access to additional methods, making it much easier to work with our database. In the end, I'll be able to interact with my tables like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;playlist&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Playlist&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;first&lt;/span&gt;

&lt;span class="nb"&gt;p&lt;/span&gt; &lt;span class="n"&gt;playlist&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;name&lt;/span&gt; &lt;span class="c1"&gt;# =&amp;gt; "Very Best of the 90's"&lt;/span&gt;
&lt;span class="nb"&gt;p&lt;/span&gt; &lt;span class="n"&gt;playlist&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;tracks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sample&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;name&lt;/span&gt; &lt;span class="c1"&gt;# =&amp;gt; "Step By Step"&lt;/span&gt;
&lt;span class="nb"&gt;p&lt;/span&gt; &lt;span class="n"&gt;playlist&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;albums&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sample&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;name&lt;/span&gt; &lt;span class="c1"&gt;# =&amp;gt; "Siamese Dream"&lt;/span&gt;
&lt;span class="nb"&gt;p&lt;/span&gt; &lt;span class="n"&gt;playlist&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;artists&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sample&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;name&lt;/span&gt; &lt;span class="c1"&gt;# =&amp;gt; "Alanis Morissette"&lt;/span&gt;

&lt;span class="nb"&gt;p&lt;/span&gt; &lt;span class="n"&gt;playlist&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;albums&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sample&lt;/span&gt;
          &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;tracks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;first&lt;/span&gt;
          &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;playlists&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sample&lt;/span&gt;
          &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;artists&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;first&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;name&lt;/span&gt; &lt;span class="c1"&gt;# =&amp;gt; "Fleetwood Mac"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Setup
&lt;/h2&gt;

&lt;p&gt;In the interest of making this article as short as possible, I won't go over how to setup Active Record or how to create the initial database tables &amp;amp; table models. To start off, I have a database schema that looks like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# db/schema.rb&lt;/span&gt;

&lt;span class="c1"&gt;# ...&lt;/span&gt;

  &lt;span class="n"&gt;create_table&lt;/span&gt; &lt;span class="s2"&gt;"albums"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;force: :cascade&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
    &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt; &lt;span class="s2"&gt;"name"&lt;/span&gt;
    &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;datetime&lt;/span&gt; &lt;span class="s2"&gt;"release_data"&lt;/span&gt;
    &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt; &lt;span class="s2"&gt;"img_url"&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="n"&gt;create_table&lt;/span&gt; &lt;span class="s2"&gt;"artists"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;force: :cascade&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
    &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt; &lt;span class="s2"&gt;"name"&lt;/span&gt;
    &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;integer&lt;/span&gt; &lt;span class="s2"&gt;"popularity"&lt;/span&gt;
    &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt; &lt;span class="s2"&gt;"img_url"&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="n"&gt;create_table&lt;/span&gt; &lt;span class="s2"&gt;"playlists"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;force: :cascade&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
    &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt; &lt;span class="s2"&gt;"name"&lt;/span&gt;
    &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt; &lt;span class="s2"&gt;"img_url"&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="n"&gt;create_table&lt;/span&gt; &lt;span class="s2"&gt;"tracks"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;force: :cascade&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
    &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt; &lt;span class="s2"&gt;"name"&lt;/span&gt;
    &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;integer&lt;/span&gt; &lt;span class="s2"&gt;"duration_s"&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Setting Up Associations
&lt;/h2&gt;

&lt;p&gt;Notice the diagram at the beginning of this article. The "Playlists" table and "Artists" table are nowhere near close to each-other, but by using Active Record associations, we can directly access all the artists represented in a specific playlist by simply calling &lt;code&gt;.artists&lt;/code&gt; on an instance of &lt;code&gt;Playlist&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;playlist&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Playlist&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;first&lt;/span&gt;
&lt;span class="n"&gt;artist&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Artist&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;first&lt;/span&gt;

&lt;span class="nb"&gt;p&lt;/span&gt; &lt;span class="n"&gt;playlist&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;artists&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pluck&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:name&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;uniq&lt;/span&gt;
  &lt;span class="c1"&gt;# =&amp;gt;  ["Post Malone", "Kid Cudi", "Mr. Probz", "Miley Cyrus",&lt;/span&gt;
  &lt;span class="c1"&gt;#       "Fleetwood Mac","The xx", "Elton John", "Wiz Khalifa"]&lt;/span&gt;

&lt;span class="c1"&gt;# It works both ways&lt;/span&gt;
&lt;span class="nb"&gt;p&lt;/span&gt; &lt;span class="n"&gt;artist&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;playlists&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pluck&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="c1"&gt;# =&amp;gt; ["Oldies", "Classic Hits"]&lt;/span&gt;


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

&lt;/div&gt;






&lt;h4&gt;
  
  
  Quick Explanation for &lt;code&gt;#pluck&lt;/code&gt;:
&lt;/h4&gt;

&lt;p&gt;&lt;code&gt;#pluck&lt;/code&gt; is very useful method, provided by Active Record. It return an array of values when called on a collection of records. &lt;a href="https://apidock.com/rails/ActiveRecord/Calculations/pluck"&gt;apidock.com&lt;/a&gt; says this about &lt;code&gt;#pluck&lt;/code&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"&lt;strong&gt;Use &lt;code&gt;#pluck&lt;/code&gt; as a shortcut to select one or more attributes without loading a bunch of records just to grab the attributes you want.&lt;/strong&gt;"&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;I've created four models (so far) representing the Playlists, Albums, Artists, &amp;amp; Tracks tables.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--qu-B9y6K--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4lzojk5cz1orhz8eza08.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--qu-B9y6K--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4lzojk5cz1orhz8eza08.png" alt="model files" width="211" height="229"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, I'll create the table associations for each model, starting with Artists. Let's look at our database diagram again:&lt;/p&gt;

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

&lt;p&gt;Thinking it through, it seems reasonable to say that each artist would have many albums. So inside our artist model, we can describe that association with a &lt;code&gt;has_many&lt;/code&gt; macro, like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# app/models/artist.rb&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Artist&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ActiveRecord&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Base&lt;/span&gt;
  &lt;span class="n"&gt;has_many&lt;/span&gt; &lt;span class="ss"&gt;:albums&lt;/span&gt; &lt;span class="c1"&gt;# &amp;lt;- plural&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And, inside our album model, we can reciprocate this association by using a &lt;code&gt;belongs_to&lt;/code&gt; macro:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# app/models/album.rb&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Album&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ActiveRecord&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Base&lt;/span&gt;
  &lt;span class="n"&gt;belongs_to&lt;/span&gt; &lt;span class="ss"&gt;:artist&lt;/span&gt; &lt;span class="c1"&gt;# &amp;lt;- singular&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Note - make sure to use the correct singular/plural form of the table name when creating the associations.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Continuing, each album has many tracks &amp;amp; each track belongs to a single album (in our case). Adding to our album model:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# app/models/album.rb&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Album&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ActiveRecord&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Base&lt;/span&gt;
  &lt;span class="n"&gt;belongs_to&lt;/span&gt; &lt;span class="ss"&gt;:artist&lt;/span&gt;
  &lt;span class="n"&gt;has_many&lt;/span&gt; &lt;span class="ss"&gt;:tracks&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And inside the track model:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Track&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ActiveRecord&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Base&lt;/span&gt;
  &lt;span class="n"&gt;belongs_to&lt;/span&gt; &lt;span class="ss"&gt;:album&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Before going any further, I want to check if what we have so far works. But, first, I need to add foreign-keys to my album &amp;amp; track models, by creating a new migration.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;#db/migrate/20220402193754_add_foreign_keys_to_albums_and_tracks.rb&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AddForeignKeysToAlbumsAndTracks&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ActiveRecord&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Migration&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;6.1&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;change&lt;/span&gt;
    &lt;span class="n"&gt;add_column&lt;/span&gt; &lt;span class="ss"&gt;:albums&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:artist_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:integer&lt;/span&gt;
    &lt;span class="n"&gt;add_column&lt;/span&gt; &lt;span class="ss"&gt;:tracks&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:album_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:integer&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, I can retrieve all an artist's tracks by calling:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="no"&gt;Track&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;joins&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;album: &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:artist&lt;/span&gt;&lt;span class="p"&gt;]).&lt;/span&gt;&lt;span class="nf"&gt;where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:artist&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:name&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"Nine Inch Nails"&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;&lt;span class="sb"&gt;`
  # returns an array of all tracks by "Nine Inch Nails"
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;&lt;em&gt;Note - &lt;code&gt;#joins&lt;/code&gt; &amp;amp; &lt;code&gt;#where&lt;/code&gt; are finder methods, provided by Active Record, for querying a database. You can learn more about them &lt;a href="https://guides.rubyonrails.org/active_record_querying.html"&gt;here&lt;/a&gt;&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Everything is good, so far, let's continue.&lt;/p&gt;

&lt;p&gt;Our last direct association is a different from the previous two. Continuing to think it through, each playlist has many tracks, but each track could also have many playlists. In order to represent this relationship, we need to create a new table to join together our tracks table &amp;amp; playlists table (see diagram above).&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating a Join Table
&lt;/h2&gt;

&lt;p&gt;In a new migration file, I'll put the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CreatePlaylistTracksTable&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ActiveRecord&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Migration&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;6.1&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;change&lt;/span&gt;
    &lt;span class="n"&gt;create_table&lt;/span&gt; &lt;span class="ss"&gt;:playlist_tracks&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;integer&lt;/span&gt; &lt;span class="ss"&gt;:playlist_id&lt;/span&gt;
      &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;integer&lt;/span&gt; &lt;span class="ss"&gt;:tracks_id&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will create the joins table to link our tracks &amp;amp; playlists tables together in a many-to-many relationship. Next, I need to create a new model for this table.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;PlaylistTrack&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ActiveRecord&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Base&lt;/span&gt;
  &lt;span class="n"&gt;belongs_to&lt;/span&gt; &lt;span class="ss"&gt;:playlist&lt;/span&gt;
  &lt;span class="n"&gt;belongs_to&lt;/span&gt; &lt;span class="ss"&gt;:track&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With that, my entire database is now connected. I can now chain together methods to make queries like...&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;artists&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Artists&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;joins&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;album: &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;tracks: &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:playlists&lt;/span&gt;&lt;span class="p"&gt;]])&lt;/span&gt;
                 &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:playlist&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:name&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"Very Best of the 90's"&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;which should give me a list of artists represented in the playlist, "Very Best of the 90's".&lt;/p&gt;

&lt;p&gt;I should now be able to retrieve any data I'll need from the database. But the query above is kinda ugly. I'd rather write something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;artists&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Playlist&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find_by&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;name: &lt;/span&gt;&lt;span class="s2"&gt;"Very Best of the 90's"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;artists&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In order to be able to make this call, I need to set up some more associations.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping Up Associations
&lt;/h2&gt;

&lt;p&gt;To supercharge my database queries, I added a few more associations to my models:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# app/models/playlist.rb&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Playlist&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ActiveRecord&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Base&lt;/span&gt;
  &lt;span class="n"&gt;has_many&lt;/span&gt; &lt;span class="ss"&gt;:playlist_tracks&lt;/span&gt;
  &lt;span class="n"&gt;has_many&lt;/span&gt; &lt;span class="ss"&gt;:tracks&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;through: :playlist_tracks&lt;/span&gt;
  &lt;span class="n"&gt;has_many&lt;/span&gt; &lt;span class="ss"&gt;:albums&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;through: :tracks&lt;/span&gt;
  &lt;span class="n"&gt;has_many&lt;/span&gt; &lt;span class="ss"&gt;:artists&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;through: :albums&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="c1"&gt;# app/models/track.rb&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Track&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ActiveRecord&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Base&lt;/span&gt;
  &lt;span class="n"&gt;belongs_to&lt;/span&gt; &lt;span class="ss"&gt;:album&lt;/span&gt;
  &lt;span class="n"&gt;has_one&lt;/span&gt; &lt;span class="ss"&gt;:artist&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;through: :album&lt;/span&gt;
  &lt;span class="n"&gt;has_many&lt;/span&gt; &lt;span class="ss"&gt;:playlist_tracks&lt;/span&gt;
  &lt;span class="n"&gt;has_many&lt;/span&gt; &lt;span class="ss"&gt;:playlists&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;through: :playlist_tracks&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="c1"&gt;# app/models/album.rb&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Album&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ActiveRecord&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Base&lt;/span&gt;
  &lt;span class="n"&gt;belongs_to&lt;/span&gt; &lt;span class="ss"&gt;:artist&lt;/span&gt;
  &lt;span class="n"&gt;has_many&lt;/span&gt; &lt;span class="ss"&gt;:tracks&lt;/span&gt;
  &lt;span class="n"&gt;has_many&lt;/span&gt; &lt;span class="ss"&gt;:playlists&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;through: :tracks&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="c1"&gt;# app/models/artist.rb&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Artist&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ActiveRecord&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Base&lt;/span&gt;
  &lt;span class="n"&gt;has_many&lt;/span&gt; &lt;span class="ss"&gt;:albums&lt;/span&gt;
  &lt;span class="n"&gt;has_many&lt;/span&gt; &lt;span class="ss"&gt;:tracks&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;through: :albums&lt;/span&gt;
  &lt;span class="n"&gt;has_many&lt;/span&gt; &lt;span class="ss"&gt;:playlists&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;through: :tracks&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With this setup, I can now make super simple queries like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;artists&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Playlist&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;artists&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pluck&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:name&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;uniq&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will return a list of all the artists in a playlist. That's pretty cool.&lt;/p&gt;

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

&lt;p&gt;And that's it. Now my queries are supercharged and I can write methods that work with this setup to make complex queries a breeze.&lt;br&gt;
Thanks for reading!&lt;/p&gt;

</description>
    </item>
    <item>
      <title>I Made a Hook!</title>
      <dc:creator>Eric</dc:creator>
      <pubDate>Sun, 16 Jan 2022 03:51:04 +0000</pubDate>
      <link>https://dev.to/eric_havey/i-made-a-hook-4l9n</link>
      <guid>https://dev.to/eric_havey/i-made-a-hook-4l9n</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;In 2021, you can't learn React without learning about Hooks. According to the authority, &lt;a href="http://www.reactjs.org"&gt;React&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Hooks are functions that let you “hook into' React state and lifecycle features from function components. ...A &lt;em&gt;custom Hook&lt;/em&gt; is a JavaScript function whose name starts with ‘use’ and that may call other Hooks.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In other words, Hooks are functions that are able to use React features and syntax, most notably, the built-in Hooks &lt;code&gt;useState&lt;/code&gt; &amp;amp; &lt;code&gt;useEffect&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In my VERY early journey into learning React, Hooks have been useful to me for separating complex or distracting logic from React components into their own files/functions, which cleans up my components. I like this because it makes the more important logic standout and my components easier to comprehend overall. Refactoring custom Hooks into their own files also makes them reusable throughout my entire application. As my applications grow, this versatility will become more and more critical in keeping my code DRY and easy to comprehend.&lt;/p&gt;

&lt;p&gt;One almost unavoidable task when building an app is requesting data with a fetch request. For my second of five projects in my coding bootcamp, I’m building a restaurant point-of-sales (POS) application. Important setup data, like a menu or a list of saved customers, are stored in a json file that requires a fetch request to retrieve and use. For this article, however, I'll be using the &lt;a href="https://pokeapi.co/docs/v2"&gt;POKEAPI&lt;/a&gt; in my examples, if only to make them easier to follow. You can check out my restaurant POS &lt;a href="https://github.com/theFlexOne/pos-pizza"&gt;&lt;em&gt;here&lt;/em&gt;&lt;/a&gt; if you'd like.&lt;/p&gt;

&lt;p&gt;First, I'll quickly explain how I make basic fetch requests in React, without using any custom Hooks. After that, I'll demonstrate how I created a custom Hook to do the same thing, as well as, go over their differences.&lt;/p&gt;



&lt;h2&gt;
  
  
  Making a basic fetch request (in React)
&lt;/h2&gt;

&lt;p&gt;Below is an example of how to make a fetch request inside a React component and store the results/error within a piece of state.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useEffect&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;POKEMON_URL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://pokeapi.co/api/v2/pokemon&lt;/span&gt;&lt;span class="dl"&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="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;pokemon&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setPokemon&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="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;isLoading&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setIsLoading&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="kc"&gt;false&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;error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setError&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="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nx"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;setIsLoading&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;POKEMON_URL&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;pokeData&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;setPokemon&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;pokeData&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&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;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nx"&gt;setError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;})&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;finally&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;setIsLoading&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[]);&lt;/span&gt;

  &lt;span class="c1"&gt;// Example usage of pokemon data&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;pokemonCards&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;pokemon&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;results&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;poke&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// function logic...&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="c1"&gt;// Conditional JSX template...&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 initiated three separate pieces of state to handle the fetch call:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;pokemon&lt;/em&gt; – stores the value of a successful fetch request,&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;error&lt;/em&gt; – contains any errors that may occur,&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;isLoading&lt;/em&gt; – a boolean indicating whether or not a fetch request is currently taking place.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If the request is successful, the response is stored in &lt;code&gt;results&lt;/code&gt;, otherwise, I have a &lt;code&gt;catch&lt;/code&gt; function that stores the error in &lt;code&gt;error&lt;/code&gt;, if the fetch fails. After the fetch is resolved, regardless of the results, I need to set &lt;code&gt;isLoading&lt;/code&gt; back to false, which is handled inside &lt;code&gt;finally()&lt;/code&gt; Since fetching data is asynchronous, meaning it takes some time to complete, &lt;code&gt;isLoading&lt;/code&gt; gets set to true until the fetch either succeeds or fails, and is false while nothing is being fetched. Now, I can use the pokemon data I've fetched in the rest of my application just like any other piece of state.&lt;/p&gt;

&lt;p&gt;As mentioned above, I find custom hooks useful for separating the logic inside my components into their own functions and/or files, leaving only the essence of what my component is intended for. This lightens up my component and makes comprehending it a lot easier. Also, my &lt;code&gt;useFetch&lt;/code&gt; Hook can now be reused by any component, giving my fetch call more utility, as it’s no longer confined to only one component.&lt;/p&gt;



&lt;h2&gt;
  
  
  My custom Hook - &lt;code&gt;useFetch&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;The block of code below does exactly the same thing as the previous code block, only the fetch logic is entirely inside of my &lt;code&gt;useFetch&lt;/code&gt; Hook (function), including my three state variables. I've also added an &lt;code&gt;AbortController&lt;/code&gt; to my Hook to "cleanup" my &lt;code&gt;useEffect&lt;/code&gt; Hook.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;App.js&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useEffect&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;POKEMON_URL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://pokeapi.co/api/v2/pokemon&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;useFetch&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;pokemon&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setPokemon&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="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;isLoading&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setIsLoading&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="kc"&gt;false&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;error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setError&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="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nx"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;controller&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;AbortController&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;signal&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;controller&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;setIsLoading&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;POKEMON_URL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;signal&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;pokeData&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;setPokemon&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;pokeData&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;setError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;finally&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;setIsLoading&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;controller&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;abort&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[]);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;pokemon&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;isLoading&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&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="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;pokemon&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;isLoading&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useFetch&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="c1"&gt;// Example usage of pokemon data&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;pokemonCards&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;pokemon&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;results&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;poke&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// function logic...&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="c1"&gt;// conditional JSX template...&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;Moving my fetch logic into it's own custom Hook makes my component easier to understand. I think it's pretty obvious that &lt;code&gt;useFetch&lt;/code&gt; is a function that makes a fetch call. Code that's easy to read is highly encouraged, from what I've gathered, and it makes sense, especially when collaborating with others. I hate when I have to reread my old code a few times to understand what it does.&lt;/p&gt;

&lt;p&gt;Note: it’s always best for custom Hooks to start with the word ‘use’ followed by whatever you want (useFetch, useState, useEffect). This is to let other programmers and react know right away that the function is a react Hook. I'm probably oversimplifying it, so if you want to know more, you can check out the docs for React, &lt;a href="https://reactjs.org/docs/hooks-custom.html#extracting-a-custom-hook"&gt;&lt;em&gt;here&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;



&lt;h2&gt;
  
  
  Refactoring into &lt;code&gt;useFetch.js&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Technically, I did it. I made a custom Hook. It doesn't need to be refactored into a separate file to be a custom Hook (I only say that because that was my impression, at first), but doing so but doing so has a couple advantages for me. First, it will make my component MUCH cleaner and, more importantly, I can make it even more reusable, allowing me to import it into any custom Hook or component.&lt;/p&gt;



&lt;p&gt;&lt;em&gt;App.js&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;useFetch&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;../hooks/useFetch&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;POKEMON_URL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://pokeapi.co/api/v2/pokemon&lt;/span&gt;&lt;span class="dl"&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="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;results&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;pokemon&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;isLoading&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useFetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;POKEMON_URL&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// Example usage of pokemon data&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;pokemonCards&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;pokemon&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;results&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;poke&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// function logic...&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="c1"&gt;// conditional JSX template...&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;useFetch.js&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useEffect&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="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;useFetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;results&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setResults&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="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;isLoading&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setIsLoading&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="kc"&gt;false&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;error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setError&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="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nx"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;setIsLoading&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;controller&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;AbortController&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;signal&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;controller&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;signal&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;setResults&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;setError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;finally&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;setIsLoading&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;controller&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;abort&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;url&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="nx"&gt;results&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;isLoading&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&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 think that looks WAY cleaner and makes reading it MUCH easier. This way, I'm able to get rid of all of the &lt;code&gt;useFetch&lt;/code&gt; logic in &lt;code&gt;App.js&lt;/code&gt;, including my three state variables, as well as, my &lt;code&gt;useState&lt;/code&gt; &amp;amp; &lt;code&gt;useFetch&lt;/code&gt; imports. All I have to do is import &lt;code&gt;useFetch&lt;/code&gt; at the top and invoke it, destructuring the my three state variables from it's return. Notice I've changed the name of the 'pokemon' state variable to 'results', to make it more universal. Notice I did, however, rename it to 'pokemon' when destructuring it inside &lt;code&gt;App.js&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The logic inside of &lt;code&gt;useFetch.js&lt;/code&gt; is basically cut right from &lt;code&gt;App.js&lt;/code&gt;. The only difference is I've made it more dynamic by creating a 'url' parameter so I can use my Hook to call other endpoints, if necessary.&lt;/p&gt;

&lt;p&gt;When creating custom Hooks, I always store them inside a folder called &lt;code&gt;hooks&lt;/code&gt;, located just inside the &lt;code&gt;src&lt;/code&gt; folder (&lt;code&gt;/src/hooks/useFetch.js&lt;/code&gt;). This is the most common way to structure your hook files, from my experience.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s---yzdIGND--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/75nx7rmj0m5u13fxv0cy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s---yzdIGND--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/75nx7rmj0m5u13fxv0cy.png" alt="Folder structure" width="262" height="228"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It’s also best-practice for the file name and the Hook name to be the same. Also, you should export the function by default.&lt;/p&gt;



&lt;h2&gt;
  
  
  Conditional rendering
&lt;/h2&gt;

&lt;p&gt;Once I've destructured my state variables from &lt;code&gt;useFetch()&lt;/code&gt;, I can use them to conditionally output JSX based on the their current values.&lt;/p&gt;

&lt;p&gt;From my &lt;code&gt;App.js&lt;/code&gt; examples above...&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;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="c1"&gt;// conditional JSX template...&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This portion of code is commented out to make my examples shorter and less overwhelming, but now I'll open it up and show one way to use state to conditionally output JSX.&lt;/p&gt;

&lt;p&gt;Hopefully, your familiar with conditional rendering, in general, but if not, you can learn more about it &lt;a href="https://reactjs.org/docs/conditional-rendering.html#gatsby-focus-wrapper"&gt;&lt;em&gt;here&lt;/em&gt;&lt;/a&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;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;pokemon&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;isLoading&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&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="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;FetchHook&lt;/span&gt;&lt;span class="dl"&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;pokemon&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;results&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;poke&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
          &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;i&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;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;poke&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;        &lt;span class="p"&gt;))}&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/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="nx"&gt;isLoading&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&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="nx"&gt;Loading&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;}
&lt;/span&gt;    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;isLoading&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&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="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&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;h2&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;ERROR&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h2&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/p&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="p"&gt;)}&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Above, there's three possible templates being rendered, but none at the same time. First, I checked if the &lt;code&gt;pokemon&lt;/code&gt; variable was truthy, meaning it wasn't empty, and I also made sure &lt;code&gt;isLoading&lt;/code&gt; was set to false, meaning the fetch request was resolved. Currently, I'm simply outputting each pokemon's name inside a &lt;code&gt;div&lt;/code&gt;, but if I were to take this further and make a pokedex, I could map through the results to create an interactive list of pokemon cards or whatever.&lt;/p&gt;

&lt;p&gt;Second, whenever &lt;code&gt;isLoading&lt;/code&gt; is true, I wanted to output a message saying so. This is where a loading spinner or a skeleton could be rendered.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--9MxIT54B--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/94nm3j3mle7jy301au5k.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--9MxIT54B--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/94nm3j3mle7jy301au5k.gif" width="498" height="328"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And third, if &lt;code&gt;errors&lt;/code&gt; is ever true, meaning there was an error while fetching the data, I wanted to output that information to let the user know, as well as, make sure &lt;code&gt;isLoading&lt;/code&gt; was set back to false.&lt;/p&gt;

&lt;p&gt;To bring this article full circle, because I extracted &lt;code&gt;useEffect&lt;/code&gt; into it's own file, the rest of my &lt;code&gt;App&lt;/code&gt; component can focus on it's intended purpose, which is to output a list of pokemon, making the code easier to comprehend on the first read-through.&lt;/p&gt;



&lt;h2&gt;
  
  
  More info on Hooks
&lt;/h2&gt;

&lt;p&gt;Unlike React components, Hooks can have any return value, not just valid JSX. For example, &lt;code&gt;useState&lt;/code&gt; returns a state variable and a function to set it, that is destructured from calling &lt;code&gt;useState()&lt;/code&gt;. &lt;code&gt;useEffect&lt;/code&gt;, on the other hand, doesn't return anything.&lt;/p&gt;

&lt;p&gt;By definition (see above), Hooks can call other Hooks, including &lt;code&gt;useState&lt;/code&gt;, meaning Hooks can initialize and manipulate state. That's part of what make custom Hooks so powerful! This also means that my three state variables can only be updated from within &lt;code&gt;useFetch.js&lt;/code&gt;, unless I include their set functions in the return. There should never be a reason for me to update these variables from outside the file it lives in besides refetching the data, but if there ever is one, I can always go into &lt;code&gt;useFetch.js&lt;/code&gt; and simply export whichever set function I need.&lt;/p&gt;



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

&lt;p&gt;So with that... I made a Hook! If you want to know more about Hooks, custom Hooks, or React in general, the best place is at &lt;a href="reactjs.org"&gt;reactjs.org&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;There were a few videos on YouTube that really helped me understand making custom Hooks, specifically making a custom &lt;code&gt;useFetch&lt;/code&gt; Hook. In general, I owe these guys a lot for teaching me everything:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://www.youtube.com/watch?v=Vspeudp-M9k"&gt;"How to Fetch Data in React With A Custom useFetch Hook"&lt;/a&gt; - from &lt;a href="https://www.youtube.com/channel/UC8S4rDRZn6Z_StJ-hh7ph8g"&gt;PedroTech&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.youtube.com/watch?v=Jl4q2cccwf0"&gt;"Full React Tutorial #20 - Making a Custom Hook"&lt;/a&gt; - from &lt;a href="https://www.youtube.com/channel/UCW5YeuERMmlnqo4oq8vwUpg"&gt;The Net Ninja&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.youtube.com/watch?v=qzi-X3quu3w&amp;amp;t=714s"&gt;"React 2021 Custom Hooks with LocalStorage &amp;amp; axios - Episode 18"&lt;/a&gt; - from &lt;a href="https://www.youtube.com/channel/UCTBGXCJHORQjivtgtMsmkAQ"&gt;Steve Griffith - Prof3ssorSt3v3&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you've made it this far, thank you, sincerely, for reading my article. This is only the third blog post I've ever made, so if I've made any huge mistakes or you want to give me advice on how to do this better, please, let me know!&lt;/p&gt;



&lt;p&gt;That's it.&lt;/p&gt;



&lt;p&gt;- END -&lt;/p&gt;

</description>
      <category>usefetch</category>
      <category>react</category>
      <category>hooks</category>
      <category>fetch</category>
    </item>
    <item>
      <title>Retrieving Client’s Current Position in the Browser</title>
      <dc:creator>Eric</dc:creator>
      <pubDate>Sat, 30 Oct 2021 01:36:58 +0000</pubDate>
      <link>https://dev.to/eric_havey/retrieving-clients-current-position-in-the-browser-3ip9</link>
      <guid>https://dev.to/eric_havey/retrieving-clients-current-position-in-the-browser-3ip9</guid>
      <description>&lt;p&gt;One of the projects that comes up in just about every YouTube video with a title like, “10 projects every beginner should make,” is a weather app. It’s a project that requires making a request for weather data from an API and displaying said data in the DOM. It’s actually the first real project I've attempted and it's the final project for phase one of my coding bootcamp. It helped me to learn the Fetch API and asynchronous JavaScript. I would definitely recommend it.&lt;/p&gt;

&lt;p&gt;I wanted my weather app to automatically fetch and display the weather for the client’s current position, on page load. Learning to do so also taught me how to use the browser’s built in &lt;strong&gt;Navigator&lt;/strong&gt; object to retrieve the latitude &amp;amp; longitude for the user's device. I thought it was pretty cool, so I wanted to share with y'all how I did it.&lt;/p&gt;

&lt;p&gt;If you would like to check out my weather app, you can find it in GitHub, &lt;a href="https://github.com/theFlexOne/project-1-weather-app"&gt;here&lt;/a&gt;. As of being published, I'm nowhere close to being done building the app. It successfully fetches data from three separate external APIs, but there is much work to do, still, on the frontend. Let me know what you think! Like I said, it's the final project for the first phase of my coding bootcamp, so feel free to give me some feedback on &lt;a href="http://www.github.com/theflexone"&gt;GitHub!&lt;/a&gt; Here's a screenshot of how it currently looks.&lt;/p&gt;

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

&lt;p&gt;Note: You will need to generate your own API keys from openweathermap.org and console.developers.google.com/ if you would like to see it in action. I'm currently learning how to deploy the app on netlify.com, and I will post a link to the finished app when it's ready.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;What is the &lt;em&gt;Navigator&lt;/em&gt; Object?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;According to MDN:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The &lt;strong&gt;Navigator&lt;/strong&gt; interface represents the state and the identity of the user agent. It allows scripts to query it and to register themselves to carry on some activities.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So, that’s clear enough... Honestly, I don’t really know what the Navigator object is. As far as I can tell, from perusing the MDN page on it, it’s a global(window) object that contains all kinds of information about the client’s device, like information about the network connection or the device’s battery life. It also contains the &lt;code&gt;navigator.geolocation&lt;/code&gt; property, which is an object we can work with to obtain the latitude &amp;amp; longitude of the user's device.&lt;/p&gt;

&lt;p&gt;To do this, we’ll use the &lt;strong&gt;Geolocation&lt;/strong&gt; object’s built-in method “getCurrentPosition” (&lt;code&gt;navigator.gelocation.getCurrentPosition&lt;/code&gt;). After this, check out the other properties of the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Navigator"&gt;&lt;strong&gt;Navigator&lt;/strong&gt;&lt;/a&gt; object, as well. They’re pretty cool.&lt;/p&gt;

&lt;p&gt;If you pull up the console in the browser, you can enter the following code to retrieve your current position:&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="nb"&gt;navigator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;geolocation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getCurrentPosition&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nx"&gt;position&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;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;position&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;coords&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should see this familiar pop-up:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--zvxgURJv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bnurhzyzvenvub96v6gm.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--zvxgURJv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bnurhzyzvenvub96v6gm.jpg" alt="Request permission for user's location data" width="460" height="182"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Pretty cool right? It was to me, at least, when I first made this alert happen. My alert says it's from &lt;em&gt;&lt;a href="http://www.google.com"&gt;www.google.com&lt;/a&gt;&lt;/em&gt;, because that was the website I was currently at when I entered the above code into the console.&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;A Quick Aside&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Whatever you do with the user’s location data is 100% up to you. I do, however, want to emphasize the importance of using this data ethically. Obviously, we are just fiddling around here and not creating the next Facebook or Google, but, also, don’t trick anyone into using your app, just to get them to opt-in and give away their location (I was brainstorming ways to use what I’m demonstrating unethically, and that’s the best I could come up with).&lt;/p&gt;

&lt;p&gt;Finally, ignorance does not excuse you from unethical behavior, so always be aware of the ethical implications of whatever you happen to be making at whatever company you happen to work for.&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;Back to the Code&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Click “Allow” to give yourself permission to know your own location and you should see this in your console:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--T6TwNIFp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/otpu99zhum65v5aogai2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--T6TwNIFp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/otpu99zhum65v5aogai2.png" alt="console log with latitude &amp;amp; longitude" width="804" height="79"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you can see, a &lt;strong&gt;GeoLocationCoordinates&lt;/strong&gt; object is logged with the latitude &amp;amp; longitude. Feel free to google those coordinates to check if it’s accurate.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Breaking it Down&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;First off, the &lt;strong&gt;Navigator&lt;/strong&gt; object is a property of the &lt;strong&gt;Window&lt;/strong&gt; object, in the browser, similar to the &lt;strong&gt;Document&lt;/strong&gt; object. It’s a global object, so we can just type &lt;code&gt;navigator&lt;/code&gt; instead of &lt;code&gt;window.navigator&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Inside &lt;code&gt;navigator.geolocation&lt;/code&gt; lives the method &lt;strong&gt;getCurrentPosition&lt;/strong&gt; (&lt;code&gt;navigator.geolocation.getCurrentPosition&lt;/code&gt;). That’s the part of this code that actually does anything.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;getCurrentPosition&lt;/code&gt; is an asynchronous function that takes in 1 &lt;em&gt;required&lt;/em&gt; argument and 2 &lt;em&gt;optional&lt;/em&gt; arguments.&lt;/p&gt;

&lt;p&gt;The first argument is a callback function that executes once the location information is retrieved - this is where you have access to the location information and can choose what to do with it. Because it’s asynchronous, any code you want to execute afterwards is put inside this function, much like a regular fetch call chained with &lt;code&gt;.then()&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;It takes one argument, a &lt;strong&gt;GeolocationPosition&lt;/strong&gt; object. &lt;strong&gt;GeolocationPosition&lt;/strong&gt; objects have only two properties: &lt;code&gt;coords&lt;/code&gt; &amp;amp; &lt;code&gt;timestamp&lt;/code&gt;. Above, in the code we ran inside the console, we logged the &lt;code&gt;coords&lt;/code&gt; objects. Check out the second image and you'll see the &lt;code&gt;latitude&lt;/code&gt; &amp;amp; &lt;code&gt;longitude&lt;/code&gt; of the &lt;strong&gt;GeolocationCoordinates&lt;/strong&gt; object &lt;code&gt;getCurrentPosition.coords&lt;/code&gt; returned.&lt;/p&gt;

&lt;p&gt;The second argument is another callback function that handles any errors while trying to retrieve the location information. It would normally 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;function&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&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="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&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;Finally, the third argument is an object where you can specify certain options. I won’t be going over the options object at all, since I’ve never used it myself, but the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Geolocation/getCurrentPosition"&gt;MDN documentation&lt;/a&gt; explains all about it, if you want to check it out.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;How I Used the Latitude &amp;amp; Longitude&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;For my weather app, I used one of &lt;a href="http://www.openweathermap.org/api"&gt;OpenWeather's&lt;/a&gt; amazing free API's for getting weather forecasts. All I needed was a valid latitude &amp;amp; longitude, and with one call (&lt;a href="https://openweathermap.org/api/one-call-api"&gt;One Call API&lt;/a&gt;) I was able to get all the weather data I needed for a basic weather app. I destructed the lat &amp;amp; lon from the &lt;strong&gt;GeolocationPosition&lt;/strong&gt; object returned from &lt;code&gt;getCurrentPosition&lt;/code&gt;, and sent it away to OpenWeather.&lt;/p&gt;

&lt;p&gt;Here's what the final code looks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;getLatLon&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nb"&gt;navigator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;geolocation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getCurrentPosition&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;success&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;success&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;position&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;latitude&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;lat&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;longitude&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;lon&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;position&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;fetchWeather&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;lat&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;lon&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&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="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;fetchWeather&lt;/code&gt; is a function I made myself that actually makes the fetch call to OpenWeather.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;I Guess That's All&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;And that's how I did it. It was a super fun experience, figuring out how to do this, and I'm glad I could share it with someone else. There are two YouTube videos, in particular, that were instrumental in helping me understand this topic. The first is from my favorite channel for learning anything JavaScript, &lt;a href="https://www.youtube.com/c/SteveGriffith-Prof3ssorSt3v3"&gt;Steve Griffith - Prof3ssorSt3v3&lt;/a&gt; and his amazing video, &lt;a href="https://www.youtube.com/watch?v=NIAqR34eg7I"&gt;JavaScript and Geolocation&lt;/a&gt;. The other is from one of my other favorite channels, &lt;a href="https://www.youtube.com/user/shiffman"&gt;The Coding Train&lt;/a&gt; and his wonderful video, &lt;a href="https://www.youtube.com/watch?v=3ls013DBcww"&gt;2.2 Geolocation Web API - Working with Data and APIs in JavaScript&lt;/a&gt;. Thanks for reading!&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Before You Go&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;It's been 213 days since I first started learning how to code (from 3-30-21) and I'm coming up on the conclusion to phase one of five for my coding bootcamp, Flatiron. This is my first technical blog post (2nd ever) and, in fact, is a prerequisite to moving onto phase two (my weather app, mentioned at the top, is the biggest prerequisite). These last few months, since I started this journey, have been the best. I'm grateful to have stumbled onto something that, already, means so much to me.&lt;/p&gt;

&lt;p&gt;I very serious about being the best programmer, period, so I'm completely open to, and encourage, constructive criticism, as long as it's well meant. And, of course, if anything I write is incorrect or if I failed to mention a critical piece of information, please let me know as well! I sincerely appreciate you reading this whole post. Thank you.&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;References and Resources&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://developer.mozilla.org/"&gt;MDN&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Navigator"&gt;Navigator&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Geolocation"&gt;Geolocation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Geolocation/getCurrentPosition"&gt;&lt;code&gt;getCurrentPosition()&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/GeolocationPosition"&gt;GeolocationPosition&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


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




&lt;h4&gt;
  
  
  &lt;strong&gt;Credits&lt;/strong&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;cover image from &lt;a href="https://www.browserstack.com/blog/geolocation-takes-over-the-power-of-testing-websites-and-mobile-apps-around-the-world/"&gt;browserstack&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>javascript</category>
      <category>geolocation</category>
      <category>navigator</category>
      <category>beginners</category>
    </item>
    <item>
      <title>FIRST! - An Introduction</title>
      <dc:creator>Eric</dc:creator>
      <pubDate>Tue, 19 Oct 2021 05:58:32 +0000</pubDate>
      <link>https://dev.to/eric_havey/first-an-introduction-11hb</link>
      <guid>https://dev.to/eric_havey/first-an-introduction-11hb</guid>
      <description>&lt;p&gt;You are now reading my first blog post. Not just wherever you happen to be reading this, but my first blog post, ever. I am being encouraged/made-to start a technical blog by my coding boot-camp: &lt;a href="https://www.flatironschool.com"&gt;Flatiron&lt;/a&gt;. Sharing my thoughts and opinions publicly, in a forum, is not something I’m naturally comfortable with, but I really love coding (whatever that means) and I’m willing to do whatever it takes to be the best, and maybe help/inspire others, as well.&lt;/p&gt;




&lt;h3&gt;
  
  
  What to expect?
&lt;/h3&gt;

&lt;p&gt;At first, you can expect articles centered around basic HTML/CSS/JS, like “making a fetch call”, or “the difference between findIndex() &amp;amp; indexOf()”, etc., but coming from a novice. Sharing my own struggles with a given topic will hopefully be more endearing to other novices facing similar struggles.&lt;/p&gt;




&lt;h3&gt;
  
  
  Who am I?
&lt;/h3&gt;

&lt;p&gt;My name is Eric Hafvenstein. I’ve been learning HTML/CSS/JS for around seven months now and I’m about five weeks into a 40 week software-engineering course, on-line, with Flatiron. I’m still pretty green, but programming feels natural to me. I’m 33 years old, so thinking about all the years I should have been programming is dismaying, for sure. I was so close too! I remember, as a teenager, moving files around and hiding them from my mother in the File Explorer and using MS-DOS. I couldn’t tell you what I was doing with MS-DOS, but I did use it. I was one nudge away, but life became about more than computers and video game, I guess (mostly girls).&lt;/p&gt;

&lt;p&gt;Although I am sad that I’m not a programmer with close to 20 years experience, I am overjoyed that I finally found something I’m this passionate about! Programming is just fun! Whenever I get a relatively complicated piece of code to execute, I feel like I cleared a grueling dungeon.&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;em&gt;Finally&lt;/em&gt;
&lt;/h3&gt;

&lt;p&gt;These last seven months of programming have changed my life! In fact, it’s led me to Flatiron and to here, this blog post that you’re still reading. Thanks, btw, I really appreciate you getting this far. This is the end of, what I hope is, the first of many articles I post throughout my adventures in programming.&lt;/p&gt;

&lt;h4&gt;
  
  
  Credits
&lt;/h4&gt;




&lt;h5&gt;
  
  
  - &lt;a href="https://www.dafont.com/pixellife.font"&gt;&lt;strong&gt;pixellife&lt;/strong&gt;&lt;/a&gt; font in cover image by &lt;a href="http://www.williac.com/"&gt;&lt;strong&gt;William Clifford&lt;/strong&gt;&lt;/a&gt;
&lt;/h5&gt;

</description>
      <category>webdev</category>
      <category>beginners</category>
      <category>introduction</category>
      <category>programming</category>
    </item>
  </channel>
</rss>
