<?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: Steve Kim</title>
    <description>The latest articles on DEV Community by Steve Kim (@hiddencilantro).</description>
    <link>https://dev.to/hiddencilantro</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%2F485632%2F752fb74a-1d8e-432f-8079-a06ac402c240.png</url>
      <title>DEV Community: Steve Kim</title>
      <link>https://dev.to/hiddencilantro</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/hiddencilantro"/>
    <language>en</language>
    <item>
      <title>Customizing radio buttons and checkboxes with CSS</title>
      <dc:creator>Steve Kim</dc:creator>
      <pubDate>Wed, 06 Apr 2022 18:30:39 +0000</pubDate>
      <link>https://dev.to/hiddencilantro/customizing-radio-buttons-and-checkboxes-with-css-5b6g</link>
      <guid>https://dev.to/hiddencilantro/customizing-radio-buttons-and-checkboxes-with-css-5b6g</guid>
      <description>&lt;p&gt;&lt;em&gt;&lt;strong&gt;Disclaimer:&lt;/strong&gt; There's an unnecessarily long introduction that I couldn't stop myself from writing. I had no intention of baiting so feel free to skip to the TL;DR section below if you're just here for the examples.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;How much CSS do front-end developers have to know? I've heard arguments for both sides, ranging anywhere from &lt;em&gt;"it's an absolute must since CSS is directly related to what the user sees and interacts with which is ultimately all things front-end"&lt;/em&gt; to &lt;em&gt;"I've been a front-end developer for over 18 years and I've never had to write a single line of CSS during my entire career."&lt;/em&gt; But despite which end of the spectrum your opinion aligns with, I think most of us can agree that having an additional skill under your belt never hurt anyone and, if not anything, it will &lt;strong&gt;&lt;em&gt;add&lt;/em&gt;&lt;/strong&gt; to your list of developer traits than take away from it.&lt;/p&gt;

&lt;p&gt;Having said that, it's also probably worth mentioning that CSS unfortunately seems to be one of those things that are often neglected and end up being self-taught. It was covered very briefly in my bootcamp curriculum and the little amount that was introduced was kept to the basics. It is also rarely included in any of the project requirements nor is it held to a high standard during an assessment. For a newbie programmer like myself, I'd say the primary motivation behind learning and practicing more CSS usually stems from self-fulfillment and the desire to make your final product look as "professional-grade" as possible.&lt;/p&gt;

&lt;p&gt;Furthermore, I think the technical side of CSS can sometimes feel disjointed from the ability to make a web application look aesthetic because it shares close boundaries with the creative/artistic realm of web design which requires a different skillset like knowing which shades of colors to use and how to make something look visually appealing to the user.&lt;/p&gt;

&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;p&gt;So if you're at all interested in this post it must mean you're looking to customize your input type radios and checkboxes purely using CSS. Let's start with radio buttons because they're slightly simpler.&lt;/p&gt;

&lt;h3&gt;
  
  
  Radio Buttons
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmxyup5i96xha3ahd0ldk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmxyup5i96xha3ahd0ldk.png" alt="original radio button example" width="800" height="173"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvrapbeep9m0xvxark2nk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvrapbeep9m0xvxark2nk.png" alt="customized radio button example" width="800" height="410"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The first step is to change the radio buttons to our desired size.&lt;/p&gt;

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

&lt;span class="nt"&gt;input&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nt"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;"radio"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;220px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;160px&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;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fknd3gzj72kzne7f7va53.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fknd3gzj72kzne7f7va53.png" alt="enlarged radio buttons" width="800" height="327"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;BOOM. Big radio buttons. Next we set the &lt;code&gt;appearance&lt;/code&gt; property, which controls the native appearance of UI controls, to &lt;code&gt;none&lt;/code&gt;. Then we set a border (or a background color, or an image, or a combination of all three), just anything to help us actually see something appear on the page. I also got rid of the &lt;strong&gt;Yes&lt;/strong&gt; and &lt;strong&gt;No&lt;/strong&gt; text because we want these to show up &lt;em&gt;inside&lt;/em&gt; the button and not beside it. Then I added a &lt;code&gt;border-radius&lt;/code&gt; to round the edges and a &lt;code&gt;cursor: pointer&lt;/code&gt; to bring back the pointer effect when we hover.&lt;/p&gt;

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

&lt;span class="nt"&gt;input&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nt"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;"radio"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;220px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;160px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;appearance&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;none&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;border&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;solid&lt;/span&gt; &lt;span class="m"&gt;1px&lt;/span&gt; &lt;span class="m"&gt;#72978d&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#f1f5f5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;border-radius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;6px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;cursor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;pointer&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;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft3bsacef8hcollx6c6d0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft3bsacef8hcollx6c6d0.png" alt="empty custom radio buttons" width="800" height="306"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Finally, I had a decision to make about how I wanted to handle the inner text as well as the &lt;em&gt;checkmark&lt;/em&gt; graphic when the button is selected. For this particular example, it felt easy enough to simply use CSS &lt;em&gt;pseudo-classes&lt;/em&gt; and different images to achieve the desired effect.&lt;/p&gt;

&lt;p&gt;I concluded that there were essentially four different states that I needed to account for and thus four different images:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Yes [unselected]&lt;/li&gt;
&lt;li&gt;Yes [selected]&lt;/li&gt;
&lt;li&gt;No [unselected]&lt;/li&gt;
&lt;li&gt;No [selected]&lt;/li&gt;
&lt;/ol&gt;

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

&lt;span class="nt"&gt;input&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nt"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;"radio"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="nd"&gt;:first-of-type&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;background-image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sx"&gt;url('./images/yes-unselected.svg')&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;input&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nt"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;"radio"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="nd"&gt;:first-of-type:checked&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;background-image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sx"&gt;url('./images/yes-selected.svg')&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#d8e2e0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;input&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nt"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;"radio"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="nd"&gt;:last-of-type&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;background-image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sx"&gt;url('./images/no-unselected.svg')&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;input&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nt"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;"radio"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="nd"&gt;:last-of-type:checked&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;background-image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sx"&gt;url('./images/no-selected.svg')&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#d8e2e0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;You can also use different pseudo selectors or any other way that's appropriate to your code as long as you are able to grab the correct elements in applying these styles. The key is to make the images the exact size you need so that they are a perfect fit, but even if they weren't, you'd be able to add properties like &lt;code&gt;background-size&lt;/code&gt;, &lt;code&gt;background-repeat: no-repeat&lt;/code&gt;, and &lt;code&gt;background-position: center&lt;/code&gt; to ensure they show up nicely. And lastly, since I use a different &lt;code&gt;background-color&lt;/code&gt; for the &lt;strong&gt;'checked'&lt;/strong&gt; state, I also added the same color to the hover effect for a better UX.&lt;/p&gt;

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

&lt;span class="nt"&gt;input&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nt"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;"radio"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="nd"&gt;:hover&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#d8e2e0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


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

&lt;/div&gt;
&lt;h3&gt;
  
  
  Checkboxes
&lt;/h3&gt;

&lt;p&gt;So what about checkboxes then? Can we just do the same thing?&lt;br&gt;
Almost, but not quite. The gist of it is the same but checkboxes behave differently in that you're unable to add a background image. This means you lose a lot of flexibility and it creates a challenge in designing the checkbox to your desired look. What you can do, however, is hide its display, give it an id, and point to that id from a &lt;code&gt;label&lt;/code&gt; tag which &lt;strong&gt;&lt;em&gt;can&lt;/em&gt;&lt;/strong&gt; set background images. Take the following example:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5yvohgdqv4earp9et3jx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5yvohgdqv4earp9et3jx.png" alt="customized checkbox example" width="800" height="439"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I've got several checkboxes that each have an image, text, and an additional input field that appears in the same &lt;em&gt;"box"&lt;/em&gt; once clicked. The HTML for one of these checkboxes looks like this:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;

&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
   &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;input&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"checkbox"&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"beer"&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"beer"&lt;/span&gt; &lt;span class="na"&gt;checked&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;checked&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;beer&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;onChange&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;handleCheckbox&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
   &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;label&lt;/span&gt; &lt;span class="na"&gt;htmlFor&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"beer"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;span&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Beer&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;span&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
   &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;label&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
   &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;checked&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;beer&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;input&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"number"&lt;/span&gt; &lt;span class="err"&gt;...&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;&lt;em&gt;(It's actually JSX, but you get the idea.)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I'm using some local state in React to keep the form controlled and using a ternary statement to render the number field conditionally, but that's a whole another topic so we'll dial that back and stick to just the CSS portion. Just note that the &lt;code&gt;htmlFor&lt;/code&gt; property above is the JSX equivalent to using the &lt;code&gt;for&lt;/code&gt; attribute in HTML labels.&lt;/p&gt;

&lt;p&gt;So the &lt;code&gt;div&lt;/code&gt; here is representing our "checkbox" so-to-speak and inside I've got the actual checkbox &lt;code&gt;input&lt;/code&gt; which we will use CSS to hide, the &lt;code&gt;label&lt;/code&gt; (which wraps a &lt;code&gt;span&lt;/code&gt; of the text), and then the &lt;code&gt;&amp;lt;input type="number"&amp;gt;&lt;/code&gt; field which, again, will render depending on whether the checkbox is &lt;em&gt;checked&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Then I apply the following CSS:&lt;/p&gt;

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

&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;220px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;min-height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;160px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;border&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;solid&lt;/span&gt; &lt;span class="m"&gt;1px&lt;/span&gt; &lt;span class="m"&gt;#72978d&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;border-radius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;6px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="nd"&gt;:hover&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;rgb&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;216&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;226&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;224&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;input&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nt"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;"checkbox"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;none&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;label&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;220px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;160px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;inline-block&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;background-repeat&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;no-repeat&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;background-position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;50%&lt;/span&gt; &lt;span class="m"&gt;25%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;cursor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;pointer&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;label&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nt"&gt;span&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;inline-block&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;margin-top&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;label&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nt"&gt;for&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;"beer"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;background-image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sx"&gt;url('./images/icon-beer.svg')&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;input&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nt"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;"checkbox"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="nd"&gt;:checked&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nt"&gt;label&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;background-image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sx"&gt;url('./images/icon-checkmark.svg')&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;Okay, so let's break this down.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We set the &lt;code&gt;width&lt;/code&gt; and &lt;code&gt;height&lt;/code&gt; on the &lt;code&gt;div&lt;/code&gt; that will act as our container, but only use &lt;code&gt;min-height&lt;/code&gt; so that it can expand if we need to display the number field below it.&lt;/li&gt;
&lt;li&gt;We then set a different color on hover to give the user some feedback like we did with the radio buttons &lt;em&gt;(this part's not so important)&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;Then we hide the &lt;em&gt;actual&lt;/em&gt; checkbox using &lt;code&gt;display: none&lt;/code&gt; and instead fill the entire &lt;code&gt;div&lt;/code&gt; with the &lt;code&gt;label&lt;/code&gt; by using the same width and height.&lt;/li&gt;
&lt;li&gt;We also set its &lt;code&gt;display&lt;/code&gt; to &lt;code&gt;inline-block&lt;/code&gt; in order to use a block element box but without the line breaks so that it flows with surrounding content.&lt;/li&gt;
&lt;li&gt;Then we make sure to prevent the image from its default behavior, which is to repeat in both directions, and use &lt;code&gt;background-position&lt;/code&gt; to define the X and Y values (using 50% for the X value to center the image but 25% for the Y value to leave some space underneath for the &lt;code&gt;span&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;And of course we mustn't forget to bring back the mouse pointer with the &lt;code&gt;cursor&lt;/code&gt; property.&lt;/li&gt;
&lt;li&gt;Then for the &lt;code&gt;span&lt;/code&gt; of text, we use &lt;code&gt;display: inline-block&lt;/code&gt; again and set a top margin to properly position it under the image.&lt;/li&gt;
&lt;li&gt;And finally we set two background images on the label: the default image we want to display and a different image when the checkbox is &lt;em&gt;checked&lt;/em&gt;.
&lt;em&gt;(Pro-tip: Placing the label right after the hidden checkbox in the HTML makes it easy to use the &lt;strong&gt;adjacent sibling combinator&lt;/strong&gt; CSS selector to target the label when the checkbox is in its checked state.)&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Again, as with most things in the land of programming, there's likely more than one approach to produce the same results (sometimes with subtle differences between them). So I'm certain that my examples are not the only way to customize these fields; they are merely one implementation that has worked for me and I share them here hoping someone might find them useful.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;To be fair, I tend to put off CSS until the very end in all of my personal projects and I would argue that a significant amount of people probably do as well (or maybe it's just me). But one thing I noticed is that the more familiar I become with styling in CSS and utilizing certain patterns, determining how I should structure the application does become slightly more instinctive. In other words, it becomes much easier to &lt;em&gt;code for the future&lt;/em&gt; knowing that I will probably want certain containers in certain places to hold certain class names and so forth. Next I think I'll explore with some of the popular CSS frameworks that we might encounter in the industry and see how they compare. Feel free to leave me comments or suggestions!&lt;/p&gt;

</description>
      <category>css</category>
      <category>html</category>
      <category>webdev</category>
    </item>
    <item>
      <title>The Chronicles of a Rookie Developer: My 'React'ion Blog</title>
      <dc:creator>Steve Kim</dc:creator>
      <pubDate>Tue, 29 Mar 2022 21:19:03 +0000</pubDate>
      <link>https://dev.to/hiddencilantro/the-chronicles-of-a-rookie-developer-my-reaction-blog-19ei</link>
      <guid>https://dev.to/hiddencilantro/the-chronicles-of-a-rookie-developer-my-reaction-blog-19ei</guid>
      <description>&lt;p&gt;It's finally here. The long awaited 2nd edition of &lt;em&gt;The Chronicles of a Rookie Developer&lt;/em&gt;. (And yes, I just shamelessly upsold my self-made blog series. 😏)&lt;/p&gt;

&lt;p&gt;Today's piece is about none other than the most popular front-end library out there, &lt;strong&gt;ReactJS&lt;/strong&gt;. My one-liner opinion? Let's just say I can understand where its popularity stems from. But my affection won't make much of a blog post, so let's just dive right in, shall we?&lt;/p&gt;

&lt;p&gt;As with the JS post, I thought I'd start by simply sharing my first impressions, some things I've learned along the way, then maybe leave you at the end with a few thoughts going forward.&lt;/p&gt;

&lt;h3&gt;
  
  
  One. Hooked on hooks.
&lt;/h3&gt;

&lt;p&gt;I'm just going to come right out and say it. What the hook would we do without hooks? Okay that was corny. But seriously, everything is so much easier with hooks. I felt so cheated when I first encountered hook examples after spending a lot of time learning about &lt;strong&gt;functional vs. class components&lt;/strong&gt;, using &lt;strong&gt;lifecycle methods&lt;/strong&gt;, and &lt;strong&gt;&lt;em&gt;this&lt;/em&gt;&lt;/strong&gt;. Granted, not all of these things completely "go away" with hooks, and I don't regret covering all the bases because 1) I think it makes me a stronger developer and 2) I'm told there are still plenty of professional environments that use legacy code while the industry tries to catch-up. So for anyone who's just starting out on this path as I am, I still recommend you take the time to understand the old and the new. Also, I imagine that there's still a niche for class components since you could very well run into situations where it's just more sensible to use traditional methods -- whether it's to follow certain design patterns or something more subtle. (And I encourage you to comment below if you have any good examples.) But the point I want to make is that hooks are... well... they're wonderful.&lt;/p&gt;

&lt;h3&gt;
  
  
  Two. When unsure, useState.
&lt;/h3&gt;

&lt;p&gt;One thing I noticed whenever I wanted to add a new feature or improve upon an existing one, is that I'm constantly setting and using state. Even with Redux in my application, I quickly realized that the need for local state is almost completely separate of what Redux is designed to solve. Redux deals with maintaining a single source of truth and helps prevent prop drilling, but it's more closely tied to the actual data you might need throughout your application as opposed to other non-critical or &lt;em&gt;&lt;strong&gt;UI state&lt;/strong&gt;&lt;/em&gt;. For instance, when I'm dealing with how my application &lt;em&gt;behaves&lt;/em&gt; or how it should render a component, it usually means I just need to keep track of values that represent a certain state of my application.&lt;/p&gt;

&lt;p&gt;Take this example. I was building out a quiz-like feature on my application and needed to incorporate a &lt;em&gt;stepper&lt;/em&gt; to visibly show the user which question they were on because how annoying would a quiz or survey be if you had no idea how many more times you can expect to press "Next" before you're finished. So I've got a "parent" component that renders a separate component for each question in the quiz. (FYI, I am also using React Router to take the user to a new route for each of these renders.)&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;Routes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Route&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-router-dom&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;QuestionOne&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;./quiz/QuestionOne&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;QuestionTwo&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;./quiz/QuestionTwo&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;...&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Quiz&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;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;Routes&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;Route&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;element&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;lt;&lt;/span&gt;&lt;span class="nx"&gt;QuestionOne&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="sr"&gt;/&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;Route&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;2&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;element&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;lt;&lt;/span&gt;&lt;span class="nx"&gt;QuestionTwo&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;}&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;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/Routes&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;   &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;Here's the part you stop to think what information is changing and therefore should belong in state &lt;strong&gt;(the current question in the quiz)&lt;/strong&gt; and which component stays mounted and which ones come and go &lt;strong&gt;(the Quiz component is the parent that stays mounted while the Question components render on and off the page depending on the route)&lt;/strong&gt;. So then where should my stepper live and which component should keep track of which step the user is on? The answer is obviously the &lt;em&gt;parent component&lt;/em&gt;, in this case, &lt;code&gt;Quiz&lt;/code&gt;. Great, so we add that in. &lt;/p&gt;

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

&lt;span class="p"&gt;...&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Quiz&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;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;Routes&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;Route&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;element&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;lt;&lt;/span&gt;&lt;span class="nx"&gt;QuestionOne&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="sr"&gt;/&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;Route&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;2&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;element&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;lt;&lt;/span&gt;&lt;span class="nx"&gt;QuestionTwo&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;}&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;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/Routes&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;Stepper&lt;/span&gt; &lt;span class="nx"&gt;steps&lt;/span&gt;&lt;span class="o"&gt;=&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="nx"&gt;nextButton&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;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;handleNext&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;Next&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;}
&lt;/span&gt;            &lt;span class="nx"&gt;backButton&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;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;handleBack&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;Back&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&amp;gt;} /&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="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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;em&gt;(For the actual Stepper component, I used Material UI but have simplified its properties for the purpose of this example.)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The props that are being passed are pretty self-explanatory but &lt;code&gt;steps&lt;/code&gt; obviously refers to the total number of steps we want our stepper to have, whereas &lt;code&gt;nextButton&lt;/code&gt; and &lt;code&gt;backButton&lt;/code&gt; represent our two buttons that each take an &lt;code&gt;onClick&lt;/code&gt; event that will handle navigating forward and back through our quiz. So now, how can we get the stepper to actually display which step we're currently on? Enter the &lt;code&gt;useState&lt;/code&gt; hook.&lt;/p&gt;

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

&lt;span class="c1"&gt;//Quiz.js&lt;/span&gt;
&lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Quiz&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;activeStep&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setActiveStep&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
   &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
         &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Routes&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;Route&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;element&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;lt;&lt;/span&gt;&lt;span class="nx"&gt;QuestionOne&lt;/span&gt; &lt;span class="nx"&gt;setActiveStep&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;setActiveStep&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="sr"&gt;/&amp;gt;} /&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;Route&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;2&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;element&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;lt;&lt;/span&gt;&lt;span class="nx"&gt;QuestionTwo&lt;/span&gt; &lt;span class="nx"&gt;setActiveStep&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;setActiveStep&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="sr"&gt;/&amp;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="sr"&gt;/Routes&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;Stepper&lt;/span&gt; &lt;span class="nx"&gt;steps&lt;/span&gt;&lt;span class="o"&gt;=&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="nx"&gt;activeStep&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;activeStep&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="nx"&gt;nextButton&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;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;handleNext&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;Next&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;}
&lt;/span&gt;            &lt;span class="nx"&gt;backButton&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;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;handleBack&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;disabled&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;activeStep&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;Back&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&amp;gt;} /&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="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;/code&gt;&lt;/pre&gt;

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

&lt;span class="c1"&gt;//QuestionOne.js&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;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;function&lt;/span&gt; &lt;span class="nf"&gt;QuestionOne&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="nx"&gt;setActiveStep&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="nf"&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="nf"&gt;setActiveStep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
   &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[]);&lt;/span&gt;

   &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;QuestionOne&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;


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

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

&lt;span class="c1"&gt;//QuestionTwo.js&lt;/span&gt;
&lt;span class="p"&gt;...&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;QuestionTwo&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="nx"&gt;setActiveStep&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="nf"&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="nf"&gt;setActiveStep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
   &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[]);&lt;/span&gt;

   &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;QuestionTwo&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;Couple of things are happening here but first I set up some local state in my &lt;code&gt;Quiz&lt;/code&gt; component with an initial value of &lt;code&gt;0&lt;/code&gt; and name it &lt;code&gt;activeStep&lt;/code&gt;. I then pass this as a prop to my &lt;code&gt;Stepper&lt;/code&gt; component in order to tell it what step we're on (and also use it to disable the "Back" button when we're on the first step/question). Then I pass the &lt;code&gt;setActiveStep&lt;/code&gt; method to the &lt;em&gt;children&lt;/em&gt; components so that they may use it in their &lt;code&gt;useEffect&lt;/code&gt; which I have set up to basically mimic the &lt;code&gt;componentDidMount&lt;/code&gt; lifecycle.&lt;/p&gt;

&lt;p&gt;So now, whenever the user renders a Question component, the parent will know which one the user is looking at since it holds the &lt;code&gt;activeStep&lt;/code&gt; state and shares the corresponding value to the Stepper as well.&lt;/p&gt;

&lt;p&gt;Some other great examples of places I utilized local state are with my Login/Signup drawers, controlled forms, various snackbars, dialogs, toggles and many more. When building with React, you will never be short of places to use and manage state since literally any value that needs to change will mean that it needs to be stored in either local or global state.&lt;/p&gt;

&lt;p&gt;But it's important to bear in mind that there is no right answer when it comes to which of the two you should use to store your information. Even the Redux documentation will tell you that it's often a choice developers have to make and that it's important to find a good balance. Some developers are more comfortable with storing absolutely everything in a global state management tool (like Redux) whereas I personally find it an anti-pattern to include every bit of information in the global state when we can utilize local state.&lt;/p&gt;

&lt;p&gt;So next time you're wanting to develop a feature but feel stuck or clueless on where to begin, try setting up some values in state and focus on what and how those values need to change in order to implement your desired behavior.&lt;/p&gt;

&lt;h3&gt;
  
  
  Three. Keep a mental note of the component tree.
&lt;/h3&gt;

&lt;p&gt;Lastly, I would like to end with this. I learned that taking sufficient time to plan and having a solid grasp of how you will build out your component tree before you get started on a project can help tremendously with your application control flow. Once a user starts freely navigating around in your app, it quickly becomes apparent that you need to be somewhat conscious of which components are constantly mounting and unmounting. This is particularly because the lifecycle of a component is crucial in determining where certain state values should reside and if you're not making a mental note of it as you code, it can lead to some very unexpected behavior down the road (especially as your application grows bigger in both size and functionality).&lt;/p&gt;

&lt;p&gt;As always, thank you for taking the time to read and, once again, stay tuned for the next edition of &lt;em&gt;The Chronicles of a Rookie Developer&lt;/em&gt;!&lt;/p&gt;

</description>
      <category>react</category>
      <category>javascript</category>
      <category>webdev</category>
      <category>codenewbie</category>
    </item>
    <item>
      <title>The Chronicles of a Rookie Developer: JavaScript Insights</title>
      <dc:creator>Steve Kim</dc:creator>
      <pubDate>Wed, 22 Dec 2021 15:52:42 +0000</pubDate>
      <link>https://dev.to/hiddencilantro/the-chronicles-of-a-rookie-developer-javascript-insights-2jm0</link>
      <guid>https://dev.to/hiddencilantro/the-chronicles-of-a-rookie-developer-javascript-insights-2jm0</guid>
      <description>&lt;h3&gt;
  
  
  Pretext
&lt;/h3&gt;

&lt;p&gt;After building out my first-ever vanilla JS + Rails API application, I thought back on the experience and skimmed through my code to gather ideas on what I could blog about. The truth is, there were many bits and pieces that I learned but I didn't feel like I knew nearly enough about each topic to solely dedicate an entire blog post. (Not to mention I also suffer from chronic indecisiveness.) So I apologize in advance but I decided to just list them all. &lt;strong&gt;&lt;em&gt;Here are 4 things I learned, attempted, or simply found interesting about JavaScript&lt;/em&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  One. To function, or not to function, that is the question.
&lt;/h3&gt;

&lt;p&gt;In JavaScript, and particularly vanilla JS, you're most likely going to declare and use these so-called &lt;em&gt;node getters&lt;/em&gt; where you grab elements from the DOM using a method such as (but not limited to) &lt;code&gt;querySelector()&lt;/code&gt; in combination with one or more valid CSS selector strings (like classes or ids). And when you find yourself querying for the same node multiple times at difference places in your code, it makes sense to assign it to a variable and extract it to a more global scope, right?&lt;br&gt;
Now, I know that when we first start learning to code, this notion of declaring variables in the global scope is a big no-no and it gets reiterated over and over as we're often told that it can lead to some unexpected behaviors down the road and should therefore -- when possible -- be avoided. But for now, let's just assume that our application is extremely small and there is very little to no reason to sound the alarm. The question, then, is whether to wrap these node getters into a function or to just have it point directly to the node. &lt;br&gt;
For instance, you might've seen someone do something like&lt;br&gt;
&lt;code&gt;const mainContainer = () =&amp;gt; document.querySelector('div.main')&lt;/code&gt;&lt;br&gt;
versus something like&lt;br&gt;
&lt;code&gt;const header = document.querySelector('#header')&lt;/code&gt;.&lt;br&gt;
So which way is better? The answer, I've found, is that it really &lt;strong&gt;&lt;em&gt;depends&lt;/em&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;There's this subtle yet sweet balance between what you are trying to accomplish with the node and whether the node exists or doesn't exist inside a particular execution context.&lt;/p&gt;

&lt;p&gt;The benefit of using a function to grab your node is that you can always ensure you are selecting the most recent version of it since you are calling the query at the exact moment you need it. This is particularly useful when perhaps you need to grab a node that doesn't exist immediately on initial load but is something that gets created later in your code (as a result of a callback, for instance). I'd say 9 times out of 10, this is probably going to be your &lt;strong&gt;&lt;em&gt;preferred&lt;/em&gt;&lt;/strong&gt; method.&lt;/p&gt;

&lt;p&gt;However, the opposite can also be true. I ran into an occasion where it made more sense to point directly to the node, and it was something as simple as wanting to &lt;code&gt;remove()&lt;/code&gt; a header from the page and later re-attach that &lt;strong&gt;&lt;em&gt;same exact node&lt;/em&gt;&lt;/strong&gt; back on the DOM. In this case, if we were to use a function, we would not be able to find the node since it would no longer exist on the &lt;code&gt;document&lt;/code&gt; and we would instead have to re-create the element. But luckily for us, JavaScript has garbage collection, meaning it will store it in memory and give us access to it even after it's been removed from the DOM as long as we point it to a variable. It then goes without saying that this would probably merit some thought in all future applications in order to ensure that we are always effectively preventing unnecessary memory leaks.&lt;/p&gt;

&lt;h3&gt;
  
  
  Two. Two is always better than one, or is it...?
&lt;/h3&gt;

&lt;p&gt;The thing I'm talking about here is none other than the &lt;strong&gt;DRY principle&lt;/strong&gt; of programming and my humble attempt to combine two functions into one. I've learned by now that refactoring code is just a regular part of any programmer's life and should become second nature sooner rather than later. So as I examined for areas to abstract, I noticed that my fetch functions were carrying a lot of code and particularly noticed similarities between my &lt;code&gt;POST&lt;/code&gt; and &lt;code&gt;PATCH&lt;/code&gt; requests. The data being sent was identical, the fetch &lt;code&gt;url&lt;/code&gt; was identical except for the presence of an &lt;code&gt;id&lt;/code&gt; (thanks to RESTful routing), and the &lt;code&gt;init&lt;/code&gt; object was identical except for the &lt;code&gt;HTTP method&lt;/code&gt;. It seemed to check everything off the list for a potential refactor.&lt;/p&gt;

&lt;p&gt;First I should start by mentioning that I've built my application in an object-oriented pattern using ES6 class syntax and therefore have a separate &lt;code&gt;Adapter&lt;/code&gt; class that handles all fetches.&lt;br&gt;
Sticking to conventions of &lt;strong&gt;CRUD&lt;/strong&gt;, I've got a static &lt;code&gt;createRecord()&lt;/code&gt; and &lt;code&gt;updateRecord()&lt;/code&gt; method within the &lt;code&gt;Adapter&lt;/code&gt; class, each responsible for sending the appropriate fetch request. I also have one other static property, &lt;code&gt;baseURL&lt;/code&gt;, and two other static methods defined, &lt;code&gt;setDataObj()&lt;/code&gt; and &lt;code&gt;setInitObj()&lt;/code&gt;. &lt;code&gt;baseURL&lt;/code&gt; (as the name suggests) simply stores the base URL to which we will be sending our fetch requests while &lt;code&gt;setDataObj()&lt;/code&gt; is responsible for constructing the object that we will be sending off to the backend and contains all of the input values from a form. It looks something like this:&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;static&lt;/span&gt; &lt;span class="nx"&gt;setDataObj&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="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;form&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#name&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;value&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;description&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;form&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#description&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;value&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;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nx"&gt;description&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;data&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;Notice that it returns the data object, as this will be useful to us in the next step.&lt;br&gt;
Then in my &lt;code&gt;setInitObj()&lt;/code&gt; method, I take in a string argument for the type of request -- &lt;code&gt;POST&lt;/code&gt;, &lt;code&gt;PATCH&lt;/code&gt;, or &lt;code&gt;PUT&lt;/code&gt; -- then use it to build out an options object.&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;static&lt;/span&gt; &lt;span class="nx"&gt;setInitObj&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;method&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;options&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;method&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Content-Type&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;application/json&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;Accept&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;application/json&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="na"&gt;body&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="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Adapter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setDataObj&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;options&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;Notice that I am now able to simply pass in &lt;code&gt;Adapter.setDataObj()&lt;/code&gt; to &lt;code&gt;JSON.stringify()&lt;/code&gt; since we made it return the object we need.&lt;br&gt;
&lt;code&gt;setInitObj()&lt;/code&gt; then returns yet another object, which we can use in our fetch method both in &lt;code&gt;createRecord()&lt;/code&gt; or &lt;code&gt;updateRecord()&lt;/code&gt;, passing in the proper HTTP verb with it:&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;static&lt;/span&gt; &lt;span class="nx"&gt;createRecord&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="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Adapter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;baseURL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Adapter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setInitObj&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;


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

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

&lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="nx"&gt;updateRecord&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Adapter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;baseURL&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Adapter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setInitObj&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;PATCH&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;Now in my event handlers, or anywhere in my code where I need to send off the form data, I can simply call &lt;code&gt;Adapter.createRecord()&lt;/code&gt; or &lt;code&gt;Adapter.updateRecord(id)&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Three. Being conscious of how often we fetch.
&lt;/h3&gt;

&lt;p&gt;Personally, this was more of a food for thought than anything else because I'm guilty of not following my own advice but I &lt;strong&gt;&lt;em&gt;did realize&lt;/em&gt;&lt;/strong&gt; the importance of code design, particularly how I wish to maintain the data on the front-end after a fetch. Because this was my first experience with JavaScript, and especially because I was using functional vanilla JS instead of object-oriented JS or some other library, I chose the easy way out and saved myself a few headaches by re-fetching at times. Not &lt;em&gt;ALL&lt;/em&gt; the time, but in certain situations. At least now I definitely see how I &lt;strong&gt;&lt;em&gt;could&lt;/em&gt;&lt;/strong&gt; have done things and it will come in handy as I think about incorporating more features on my app like sorting and filtering.&lt;br&gt;
&lt;em&gt;(Note: This was something I wanted to share at the time of originally writing this post but have since rebuilt my entire project into object-oriented JavaScript and am now dealing with my front-end data in a much different manner.)&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Four. Default behavior of an HTML5 button is submit.
&lt;/h3&gt;

&lt;p&gt;Last but not least, I was enlightened during one of my debugging sessions that, apparently, the default behavior of a button is &lt;code&gt;submit&lt;/code&gt; unless specified otherwise. Maybe this was just me but for some reason I always thought &lt;code&gt;&amp;lt;button&amp;gt;&lt;/code&gt; tags did not have a default behavior as opposed to &lt;code&gt;&amp;lt;input type="submit"&amp;gt;&lt;/code&gt;. This would matter less if the button isn't enclosed in a &lt;code&gt;&amp;lt;form&amp;gt;&lt;/code&gt; but if you're ever trying to use buttons inside a form for something &lt;em&gt;other than submitting the form&lt;/em&gt;, you have to either specify the button's type attribute as &lt;code&gt;type="button"&lt;/code&gt; or, alternatively, use &lt;code&gt;preventDefault()&lt;/code&gt; in its event handler. Again, this might've been obvious to most but I hope someone else out there might find it useful to know!&lt;/p&gt;

&lt;p&gt;If you've made it this far, thank you for reading. Stay tuned for the next edition of &lt;em&gt;The Chronicles of a Rookie Developer&lt;/em&gt; as I continue my journey! Until next time!&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>codenewbie</category>
      <category>todayilearned</category>
    </item>
    <item>
      <title>Rails: The Quick-and-Dirty to February 31</title>
      <dc:creator>Steve Kim</dc:creator>
      <pubDate>Thu, 04 Nov 2021 16:18:27 +0000</pubDate>
      <link>https://dev.to/hiddencilantro/the-quick-and-dirty-to-february-31-3p9p</link>
      <guid>https://dev.to/hiddencilantro/the-quick-and-dirty-to-february-31-3p9p</guid>
      <description>&lt;h3&gt;
  
  
  Prologue
&lt;/h3&gt;

&lt;p&gt;If you're a newbie programmer like I am and just starting to build your very first Ruby on Rails application, there's a good chance you'll attempt to incorporate some dates in your data using good ole HTML5 forms.&lt;/p&gt;

&lt;p&gt;Whether it's inputting a user's birthdate or adding some sort of calendar feature, your instinct will be to use something like &lt;code&gt;date_select&lt;/code&gt;, which is just one of many Action View Helpers built into Rails for us to use at our disposal. And it'll work quite nicely, allowing you to include options like &lt;code&gt;start_year&lt;/code&gt;, &lt;code&gt;end_year&lt;/code&gt;, &lt;code&gt;order&lt;/code&gt;, and &lt;code&gt;prompt&lt;/code&gt;. And in your controller, you'll just add the attribute name to your strong params, pass it along to an object and rely on mass assignment to take care of the rest. Rails will perform its standard "rails-y magic" and everything will function the way you expect it to. The world is a joyful place.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Conflict
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"We keep moving forward, opening new doors, and doing new things, because we're curious and curiosity keeps leading us down new paths."&lt;br&gt;
-Walt Disney&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;You often discover issues when you get curious -- not only because you're new to coding and there's just so much that you don't know, but also because you're a programmer and programmers are usually... well... curious (and for good reasons too). So as Disney suggested, curiosity is what led me to test how Rails might handle the input of an invalid date like February 30 or 31. Because without using any JavaScript, plugins, gems or other external code, there's obviously no way to manipulate the DOM, which means no way to dynamically set the range or hide the few extra &lt;code&gt;option&lt;/code&gt; tags based on an event (like the user selecting a month, for example). The best we can hope for is for our application to spit back an error which Rails is quite equipped to deal with.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzg9spyyyilh90p4aksb9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzg9spyyyilh90p4aksb9.png" alt="Sample Form" width="800" height="251"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;...&lt;br&gt;
...&lt;br&gt;
...&lt;/p&gt;

&lt;p&gt;Fingers crossed... and &lt;code&gt;Submit&lt;/code&gt;!&lt;/p&gt;

&lt;p&gt;...&lt;br&gt;
...&lt;br&gt;
...&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs3z4qfqzysn5dwwc6f2y.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs3z4qfqzysn5dwwc6f2y.png" alt="Image description" width="362" height="294"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;...what???&lt;/p&gt;

&lt;p&gt;No error and Disney's date of birth is now March 3rd.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Rationale
&lt;/h3&gt;

&lt;p&gt;So it appears that when Rails is given an invalid date such as February 31, it takes the additional days and just rolls it over to the next month. I couldn't figure out for the life of me why Rails would believe this is more useful than just throwing an invalid date error, which I'm sure wouldn't be too difficult to implement under the hood with a bit of sanitizing and/or validating. Perhaps once I've grown as a developer and one day decide to take a deep dive into the Rails library and source code, I'll have a better understanding and when I do I will be sure to come edit this blog. I reckon there must be circumstances where this is the desired behavior but for the time being, I'm not convinced.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Fix
&lt;/h3&gt;

&lt;p&gt;There's a number of things you could do. The way &lt;code&gt;date_select&lt;/code&gt; works is that you get three separate key-value pairs coming through your params.&lt;/p&gt;

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

{"user"=&amp;gt; {
    "first_name"=&amp;gt;"Walt",
    "last_name"=&amp;gt;"Disney",
    "gender"=&amp;gt;"male",
    "birthdate(1i)"=&amp;gt;"1901",
    "birthdate(2i)"=&amp;gt;"2",
    "birthdate(3i)"=&amp;gt;"31"},
 "commit"=&amp;gt;"Submit",
 "controller"=&amp;gt;"users",
 "action"=&amp;gt;"create"}


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

&lt;/div&gt;

&lt;p&gt;But inside Rails' Active Model library is a module called Multiparameter Attribute Assignment and it's responsible for doing just that.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Instantiates objects for all attribute classes that needs more than one constructor parameter. This is done by calling new on the column type or aggregation type (through composed_of) object with these parameters. So having the pairs written_on(1) = "2004", written_on(2) = "6", written_on(3) = "24", will instantiate written_on (a date type) with Date.new("2004", "6", "24"). You can also specify a typecast character in the parentheses to have the parameters typecasted before they're used in the constructor. Use i for Integer and f for Float. If all the values for a given attribute are empty, the attribute will be set to nil.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Rails will take the three values (year, month, day) and reconstruct it into a &lt;code&gt;Date&lt;/code&gt; object before persisting it to the database. This is once again Rails at its best, making our lives convenient so that we don't have to concern ourselves with correctly assigning multiparameters to an attribute. But what this also means is that, if we wanted, we could probably monkey patch the code to prevent it from carrying the extra days over. But monkey patching is often a frowned upon practice and should be avoided when possible.&lt;/p&gt;

&lt;p&gt;Other common solutions I came across on the web mostly involved using some type of external library (various plugins and gems) or JavaScript. All very valid and possibly the obvious choice, but that's not what this blog is about. As the title suggests, I'm going to show you &lt;strong&gt;how I did it&lt;/strong&gt;, the quick-and-dirty way. No gems and no JavaScript.&lt;/p&gt;

&lt;p&gt;The answer is a simple rescue. Here's what I did:&lt;/p&gt;

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

def create
   begin
      @user = User.new(user_params)
      @user.valid?
      Date.new(user_params["birthdate(1i)"].to_i, user_params["birthdate(2i)"].to_i, user_params["birthdate(3i)"].to_i)
      if @user.save
         redirect_to @user, notice: "New user created!"
      else
         render :new
      end
   rescue ArgumentError
      @user.errors.add(:birthdate, "must be a valid date")
      @user.birthdate = nil
      render :new
   end
end


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

&lt;/div&gt;

&lt;p&gt;I utilize the fact that trying to instantiate a &lt;code&gt;Date&lt;/code&gt; object with invalid dates will actually raise &lt;code&gt;ArgumentError: invalid date&lt;/code&gt;. And when it does, I simply rescue the exception and attach an error to &lt;code&gt;:birthdate&lt;/code&gt; before re-rendering the view.&lt;/p&gt;

&lt;p&gt;You'll also notice that after I pass the params into a new &lt;code&gt;User&lt;/code&gt; instance, I call &lt;code&gt;@user.valid?&lt;/code&gt; first. This is to accumulate any other errors that the object might have after running validations on all of the other attributes like name and gender. Only then do I instantiate a &lt;code&gt;Date&lt;/code&gt; "dummy" object and pass in the three values to check whether the date is valid.&lt;/p&gt;

&lt;h3&gt;
  
  
  Final Thoughts
&lt;/h3&gt;

&lt;p&gt;So while what I did might not be the most elegant pattern or the most efficient method to validate dates, if you're project isn't regularly dealing with dates and you just need a quick workaround in a few places of your code, this could be the easiest (or at least a temporary) solution to reject invalid dates without breaking your code. I hope you've found this useful!&lt;/p&gt;

</description>
      <category>rails</category>
      <category>ruby</category>
      <category>html</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Using sessions in a stateless protocol</title>
      <dc:creator>Steve Kim</dc:creator>
      <pubDate>Fri, 12 Mar 2021 22:36:37 +0000</pubDate>
      <link>https://dev.to/hiddencilantro/using-sessions-in-a-stateless-protocol-3jpk</link>
      <guid>https://dev.to/hiddencilantro/using-sessions-in-a-stateless-protocol-3jpk</guid>
      <description>&lt;p&gt;So in building my first web application with Sinatra, I quickly realized that enabling sessions has many more use cases than just handing out cookies and signing users in and out. After all, the HTTP is a stateless protocol and that means sometimes you desperately need a way to pass arguments between different routes when it makes sense to do so. Enter, the session hash.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvkv2pytjl8i2qx6je3q9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvkv2pytjl8i2qx6je3q9.png" alt="Alt Text" width="800" height="48"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So you begin by enabling sessions and setting a session secret to keep our session data safe (although sessions will still work without a session secret, it's normally a good idea to use a randomly generated string of characters generally between 24 to 32 bytes long in order to help prevent malicious attacks).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvfhhed6ezry8jfucq1tr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvfhhed6ezry8jfucq1tr.png" alt="Alt Text" width="788" height="178"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once you've done that, the most common practical use is for handling the login/logout process of a user. Once we've authenticated a user, we log that person in by creating a key inside the session hash and storing that user's ID as its value.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fig2f7crwypp21q2jsu23.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fig2f7crwypp21q2jsu23.png" alt="Alt Text" width="508" height="42"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is important because each time we need to check whether a person is logged in, we can simply see whether we can find that user in the database based on the user ID that's stored inside the session hash.&lt;/p&gt;

&lt;p&gt;But just because that's what it's most commonly used for it doesn't -- or shouldn't -- limit how we use our session hash.&lt;/p&gt;

&lt;p&gt;For instance, perhaps you need to store foreign keys and use that data when necessary to create associations where needed:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fosq7hidw5nkqhoy0ze9s.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fosq7hidw5nkqhoy0ze9s.png" alt="Alt Text" width="566" height="36"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyv51ng8x8vwxigbdpsps.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyv51ng8x8vwxigbdpsps.png" alt="Alt Text" width="612" height="72"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Or perhaps you need to store a message to show the user that an action was properly executed:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc6gn5z7w3nfclg1v5yiq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc6gn5z7w3nfclg1v5yiq.png" alt="Alt Text" width="800" height="99"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzepj49bcapq0rqthzzhf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzepj49bcapq0rqthzzhf.png" alt="Alt Text" width="466" height="286"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So you see, it doesn't really matter WHAT you store. Whatever information you need persisted between each request can be stored in the session hash and utilized accordingly. This opens up and provides numerous ways in which the application can function more flexibly even as we navigate through a stateless protocol.&lt;/p&gt;

</description>
      <category>ruby</category>
      <category>sinatra</category>
      <category>sessions</category>
      <category>stateless</category>
    </item>
    <item>
      <title>Ruby CLI application: scraping, object relationships and single source of truth</title>
      <dc:creator>Steve Kim</dc:creator>
      <pubDate>Mon, 26 Oct 2020 22:35:38 +0000</pubDate>
      <link>https://dev.to/hiddencilantro/ruby-cli-application-scraping-object-relationships-and-single-source-of-truth-2ni4</link>
      <guid>https://dev.to/hiddencilantro/ruby-cli-application-scraping-object-relationships-and-single-source-of-truth-2ni4</guid>
      <description>&lt;p&gt;There’s an exciting aspect to building a CLI application, or rather the CLI in general. For the average user like myself who hasn’t a clue about the inner workings of a computer and has been confined to the comfort of GUIs, even just typing commands into the Terminal can give you the sensation of feeling like you’ve become some notorious hacker in a spy movie. And thus, to be able to successfully build an entire CLI-based application from scratch was truly a rewarding experience.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Goal
&lt;/h3&gt;

&lt;p&gt;I decided to build a very basic application for Premier League football (or soccer, in some countries) where it shows the current league standings, all the clubs in the league, and information for each individual club, and perhaps even stats for individual players (although I never got that far). It started off as a breeze. I thought I had a pretty good grasp of the concepts being dealt with, how I was going to obtain the data by scraping, and so on and so forth. To be fair, I had a great guide to follow, using a video demo that was done by my bootcamp instructor. All of it made so much sense when I was watching the demo, but as with most things in life, it’s one thing to &lt;em&gt;watch&lt;/em&gt; someone do it and completely another to &lt;em&gt;actually&lt;/em&gt; do it.&lt;/p&gt;

&lt;h3&gt;
  
  
  My first despair
&lt;/h3&gt;

&lt;p&gt;Scraping consumed a bulk of my time. Not fully understanding and knowing how to effectively utilize Nokogiri methods was my downfall. I was fixated on chaining my &lt;code&gt;.css&lt;/code&gt; selectors when later on I discovered that I could have much more easily grabbed the same data by joining ids and classes &lt;em&gt;directly&lt;/em&gt; to tags. For instance, a line in my scraper class that grabs a piece of data like so:&lt;/p&gt;

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

.css('.tableBodyContainer.isPL').css('tr:not(.expandable)').css('.long').text


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

&lt;/div&gt;

&lt;p&gt;could have just as easily accomplished the same thing using:&lt;/p&gt;

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

.search('tbody.tableBodyContainer.isPL span.long').text


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

&lt;/div&gt;
&lt;h3&gt;
  
  
  My second despair
&lt;/h3&gt;

&lt;p&gt;I knew two important rules about building relationships when going into this project. One was that the objects will need to follow the principle of maintaining a ‘single source of truth’ when building relationships across classes and that this should be done by having the object which “belongs-to” another object be accountable for holding the relationship. And once I’ve done that, I knew I’d be expected to establish the remaining relationships only through methods. Simple enough, right? The only problem was that this seemed much easier in my head when the relationship was &lt;strong&gt;A -&amp;lt; B &amp;gt;- C&lt;/strong&gt; as opposed to what I had to do which was &lt;strong&gt;A -&amp;lt; B -&amp;lt; C&lt;/strong&gt;. So instead of &lt;strong&gt;B&lt;/strong&gt; keeping track of both &lt;strong&gt;A&lt;/strong&gt; and &lt;strong&gt;C&lt;/strong&gt;, I needed to have &lt;strong&gt;B&lt;/strong&gt; accountable for &lt;strong&gt;A&lt;/strong&gt; and &lt;strong&gt;C&lt;/strong&gt; accountable for &lt;strong&gt;B&lt;/strong&gt;, then somehow build methods that will allow &lt;strong&gt;A&lt;/strong&gt; to interact with &lt;strong&gt;C&lt;/strong&gt; and vice versa. After building and re-building my classes over and over and hours of rubber duck debugging, I got it done.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

league = League.find_or_create_by_name(league_name)
new_club = Club.new(name, league, position, matches_played, matches_won, matches_drawn, matches_lost, goals_for, goals_against, goal_diff, points)
Player.new(new_club, player_number, player_name, player_position)


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

&lt;/div&gt;

&lt;p&gt;My &lt;em&gt;Club&lt;/em&gt; class was keeping track of my &lt;em&gt;League&lt;/em&gt; class and my &lt;em&gt;Player&lt;/em&gt; class was keeping track of my &lt;em&gt;Club&lt;/em&gt; class.&lt;br&gt;
Then I went on to build methods in my &lt;em&gt;League&lt;/em&gt; class that could communicate with my &lt;em&gt;Player&lt;/em&gt; class, like so:&lt;/p&gt;

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

def clubs
    Club.all.select {|club| club.league == self}
end

def players
    Player.all.select {|player| self.clubs.include?(player.club)}
End


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

&lt;/div&gt;

&lt;p&gt;And then finally an instance method inside my &lt;em&gt;Player&lt;/em&gt; class to access my &lt;em&gt;League&lt;/em&gt; class:&lt;/p&gt;


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

&lt;p&gt;def league&lt;br&gt;
    League.all.select {|league| league.players.include?(self)}&lt;br&gt;
End&lt;/p&gt;

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

&lt;/div&gt;
&lt;h3&gt;
&lt;br&gt;
  &lt;br&gt;
  &lt;br&gt;
  Final thoughts&lt;br&gt;
&lt;/h3&gt;

&lt;p&gt;There’s something I have yet to figure out and that’s a way to delay my deeper level scrapes until they're needed, instead of scraping all of my data in advance when the application first runs. The scraping simply takes way too long at the moment. Although I would ideally like to store the URL for my deeper scrapes as instance variables and then pass it into a scraper method as needed, this is proving to be a lot more difficult than I had anticipated primarily because of the way my second scrape is designed and the way my logic is currently built in the CLI class. Hopefully as I dive deeper into programming and become more skillful, I will be able to find a more elegant solution.&lt;/p&gt;

</description>
      <category>ruby</category>
      <category>cli</category>
      <category>scraping</category>
      <category>objects</category>
    </item>
    <item>
      <title>Taking advice from Gretzky</title>
      <dc:creator>Steve Kim</dc:creator>
      <pubDate>Thu, 08 Oct 2020 18:46:58 +0000</pubDate>
      <link>https://dev.to/hiddencilantro/why-software-engineering-4nbh</link>
      <guid>https://dev.to/hiddencilantro/why-software-engineering-4nbh</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"You miss 100% of the shots you don't take." -Wayne Gretzky&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Why software engineering? Frankly, for me, the answer to that question dates back to 15 years ago. It’s 2005, I’m in my sophomore year of high school and I’ve just picked out Web Design as an elective. I choose it because it seems like an undemanding class that I can take advantage of to garner a "free A" so-to-speak. And although I don’t wish to generalize high schoolers, I would describe myself as having been a &lt;em&gt;typical&lt;/em&gt; student. By typical I mean that I didn’t care much for studying or academics; I did those things because it was what I was &lt;em&gt;supposed&lt;/em&gt; to do. I loved video games and basketball, I hated getting up in the morning, school was a place to hang out with friends more than for going to class, I’d grab any opportunity to be dismissed early from school, I much preferred extracurricular activities over homework, and, if anyone asked, my favorite subjects were PE and lunch. That was until I took Web Design.&lt;/p&gt;

&lt;p&gt;It was the first time I experienced anything like it. I remember thinking, “Finally! A class that I don’t dread.” Or better yet, one that I actually found enjoyable and even looked forward to going. And while this was more than enough to pique my interest, I noticed as the year progressed that I was not only appreciating it, but I was also performing among the top of my class. And before I could even figure out why, my peers were starting to approach me for help. Granted it was only some very basic HTML and CSS, and while I’m getting very humbled at the start of my journey with Flatiron, at the time it was an encouraging moment for me. You see, I was a decent athlete and had decent grades across-the-board, but I had never been truly exceptional at anything. Yet what I was learning in that web design class just clicked with me. At times I simply couldn’t empathize with my peers who were struggling with concepts that seemed so obvious. I understood that it was like learning a new language, only difference being that this particular language made sense to me. I was comprehending it far better and more easily than most which brought me to the realization that I might have the right aptitude for code.&lt;/p&gt;

&lt;p&gt;This was probably the beginning for me in giving programming any real thought. For the very first time I considered web development as a viable and realistic career path that I might be able pursue. The surest evidence I got was the countless hours I had willingly spent on that class. Unlike doing assignments and projects for other subjects, I was doing more than what was required of me and I was doing it while having fun. As painful and irritating as it is when your code doesn’t function how it should, I get an odd (or maybe not so odd) rush out of fixing it and getting it to work.&lt;/p&gt;

&lt;p&gt;But somewhere along the road, life happened and I lost sight of it all. I lost sight of how much I had enjoyed coding, of how quickly time breezes by when I’m sitting in front of the computer to improve a website or figure out a bug. I lost sight of the potential I saw in myself and in a career that could have been right for me. And so here I am, many years later, using the pandemic as an excuse to finally take a stab at something I had always wondered about to see where it leads me. I’m nervous, excited, and, at times, still uncertain and doubtful, but I’m in high spirits and I’m optimistic that the industry will welcome me with open arms as long as I stay humble, positive, and dogged.&lt;/p&gt;

</description>
      <category>flatiron</category>
      <category>bootcamp</category>
      <category>blog</category>
    </item>
  </channel>
</rss>
