<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Nic Mortelliti</title>
    <description>The latest articles on Forem by Nic Mortelliti (@nicm).</description>
    <link>https://forem.com/nicm</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%2F790475%2F40752777-bbf5-453b-904e-86b5a4781c20.jpeg</url>
      <title>Forem: Nic Mortelliti</title>
      <link>https://forem.com/nicm</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/nicm"/>
    <language>en</language>
    <item>
      <title>How to use Styled Components with React</title>
      <dc:creator>Nic Mortelliti</dc:creator>
      <pubDate>Wed, 04 Jan 2023 03:40:32 +0000</pubDate>
      <link>https://forem.com/nicm/how-to-use-styled-components-with-react-49he</link>
      <guid>https://forem.com/nicm/how-to-use-styled-components-with-react-49he</guid>
      <description>&lt;p&gt;Are you tired of adhering to predetermined styling concepts? Do you find yourself lost in a spaghetti plate of CSS specificity? Well, this article will teach you how to &lt;del&gt;stick it to the man!&lt;/del&gt; approach styling from a components perspective, just like we do with React!&lt;/p&gt;

&lt;p&gt;Don't get me wrong, I greatly appreciate the ease of use provided by UI libraries, not to mention the massive amount of effort that goes into creating and maintaining those libraries. The majority of these libraries even offer some way to customize the appearance of the various components they offer. But lets say you and/or your design team have a specific vision for your application that you simply cannot achieve with the available UI libraries. Let's say, for example, you make use of an AI tool to generate some ideas for your application, as I did for my capstone project at the Flatiron School. The ideas generated for you can be very dramatic and complex. If we were to try to implement these designs with an off-the-shelf UI library, straight CSS or with inline styling, we may end up adding far too much complexity to our code making it the opposite of DRY (Don't Repeat Yourself) and very difficult to maintain.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--_pyeF746--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/34fw8ss7yq9kc15soy2a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--_pyeF746--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/34fw8ss7yq9kc15soy2a.png" alt="Space Tourism Site Designs Generated By AI" width="880" height="587"&gt;&lt;/a&gt;&lt;/p&gt;
Here's an example of AI-produced web designs for a space tourism application.



&lt;p&gt;&lt;a href="https://styled-components.com/"&gt;Styled Components&lt;/a&gt; addresses some of these issues. However, if you don't take the time to really plan out the design of your application, you may end up in a bowl of WET (Write Everything Twice) component soup, as I did on my first attempt using Styled Components.&lt;/p&gt;

&lt;p&gt;Alright, enough chit-chat, let's get to work.&lt;/p&gt;

&lt;h2&gt;
  
  
  Installation
&lt;/h2&gt;

&lt;p&gt;Installation of Styled Components is done through npm. Go ahead and install Styled Components with this:&lt;br&gt;
&lt;code&gt;npm install --save styled-components&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;With that out of the way, let's move on to setting up our application to make use of our future components.&lt;/p&gt;
&lt;h2&gt;
  
  
  Create Global Style and Theme Components
&lt;/h2&gt;

&lt;p&gt;With Styled Components we want to import global styles and a theming provider into our App component. Per the Styled Components documentation, the theme provider utilizes the context API to inject theming to all components underneath it in the component tree. This will provide us with an easy way to set our applications color scheme. Global Styles will make use of a helper function called &lt;code&gt;createGlobalStyle&lt;/code&gt; to generate a special component that will control the general styling of our application. For example, we typically put body styling at the top of our CSS file. However, with Styled Components, we put body styling in the Global Styles component.&lt;/p&gt;
&lt;h3&gt;
  
  
  Global Style Component
&lt;/h3&gt;

&lt;p&gt;As I mentioned previously, the Global Style component will house styling for our overall application (e.g. the '*' selector, our body as well as general primitives styling). Styling for specific parts of our application, like buttons, will be implemented later in their own styled component. The way I've been doing it for months (I'm a new software developer after all...) is by adding a 'styles' directory under the 'components' directory. Go ahead and create empty Global.js and Theme.js files within the new 'styles' directory.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;
src
│
└───components
|   |
│   └───styles
|       |   Global.js
|       |   Theme.js
|
|   App.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Open the new Global.js file now, we're going to add some basic styling here. When working with the Global Style, think about what you want all text to look like in your application. What should the spacing be like for the body class? Remember, our applications color scheme will be applied with the ThemeProvider where all of the colors will be set an actual color value (e.g. hex, rgb, hsl, etc.). So in the Global Styles file lets just set the margins and padding of our application. First, we need to import the &lt;code&gt;createGlobalStyle&lt;/code&gt; helper function from styled-components. Then we can add our GlobalStyles component with whatever global styling we want inside of it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;createGlobalStyle&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;styled-components&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;GlobalStyles&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;createGlobalStyle&lt;/span&gt;&lt;span class="s2"&gt;`
* {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

body {
  background-color: &lt;/span&gt;&lt;span class="p"&gt;${({&lt;/span&gt;&lt;span class="nx"&gt;theme&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;theme&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bgColor&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;;
  color: &lt;/span&gt;&lt;span class="p"&gt;${({&lt;/span&gt; &lt;span class="nx"&gt;theme&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;theme&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;color&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;;
  font-family: sans-serif;
  display: flex;
  justify-content: center;
  align-items: center;
  min-height: 100vh;
}`&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;GlobalStyles&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;Notice that we're making use of the Theme Provider prop to assign our various CSS colors. Cool! We'll get to that later...&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Save those changes, then open up our new Theme.js file. Here, we don't need to import anything. When we tie all of this in with our application we'll be importing the Theme Provider from styled-components into our App.js file. Instead, we'll just assign some colors here for our theming.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;primary&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#2ECC71&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;secondary&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#333&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;theme&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;bgColor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;secondary&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;primary&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

  &lt;span class="na"&gt;button&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;bgColor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;primary&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;secondary&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;That was pretty easy! Let's get this new stuff tied into our application.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting up application-wide context
&lt;/h2&gt;

&lt;p&gt;In the App component, lets add our new global style and theme components to our application.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;We need to remove the CSS file that React imports by default, &lt;code&gt;import "./App.css"&lt;/code&gt;. It will conflict with our Global Styles component, otherwise.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Import GlobalStyles from our Global.js file. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Import the Theme Provider from the &lt;code&gt;styled-components&lt;/code&gt; library.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Import &lt;code&gt;theme&lt;/code&gt; from our &lt;code&gt;theme.js&lt;/code&gt; file.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;In the return block for App, add the &lt;code&gt;ThemeProvider&lt;/code&gt; with a &lt;code&gt;theme&lt;/code&gt; prop pointing to the &lt;code&gt;theme&lt;/code&gt; component we imported.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Within the &lt;code&gt;ThemeProvider&lt;/code&gt;, add the &lt;code&gt;GlobalStyles&lt;/code&gt; component in a self-closing tag.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The &lt;code&gt;GlobalStyles&lt;/code&gt; component is inside the &lt;code&gt;ThemeProvider&lt;/code&gt; because our global styles are using values set within the &lt;code&gt;theme&lt;/code&gt; component (e.g. &lt;code&gt;color: ${({theme}) =&amp;gt; theme.primaryColor}&lt;/code&gt;).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;GlobalStyles&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./components/styles/Global&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ThemeProvider&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;styled-components&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;theme&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./components/styles/Theme&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="nx"&gt;App&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="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;ThemeProvider&lt;/span&gt; &lt;span class="nx"&gt;theme&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;theme&lt;/span&gt;&lt;span class="p"&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;GlobalStyles&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;App&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;

      &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* Application components go here */&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/ThemeProvider&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;That's it! If you're using React Router, the &lt;code&gt;&amp;lt;BrowserRouter &amp;gt;...&amp;lt;/BrowserRouter&amp;gt;&lt;/code&gt; component is placed after (e.g. sibling-of) &lt;code&gt;&amp;lt;GlobalStyles /&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Fun Part
&lt;/h2&gt;

&lt;p&gt;Let's make a custom component now! We're going to make a custom button that will use our theme colors and it will grow a little bit when we hover over it. After we create this button, we can import into any component that will use this style of a button.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Back in our &lt;code&gt;src/components/styles&lt;/code&gt; directory, add a new file titled &lt;code&gt;Buttons.styled.js&lt;/code&gt;. I learned that by adding &lt;code&gt;styled&lt;/code&gt; to the file name, we can more easily determine that styled components reside  within the file. As far as I know, it doesn’t serve any other purpose. So you could omit that part of the file name if you want, I suppose.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Inside Buttons.styled.js, import &lt;code&gt;styled&lt;/code&gt; from &lt;code&gt;styled-components&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Create a new exported component called &lt;code&gt;PrimaryButton&lt;/code&gt; and assign it to&lt;br&gt;
&lt;br&gt;
&lt;code&gt;styled.button``&lt;/code&gt;&lt;br&gt;
&lt;br&gt;
. This assignment is what allows us to create a custom button component.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Inside the two backticks (&lt;code&gt;&lt;/code&gt;&lt;code&gt;&lt;/code&gt;) is where we’ll add our CSS styling for the button. We can also add our hover pseudo-class to handle hovering over the button.&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

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

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;PrimaryButton&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;styled&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt;&lt;span class="s2"&gt;`
  cursor: pointer;
  border-radius: 0;
  border: none;
  font-size: 2em;
  margin: 0.5em;
  padding: 0.5em 1em;
  background-color: &lt;/span&gt;&lt;span class="p"&gt;${({&lt;/span&gt; &lt;span class="nx"&gt;theme&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;theme&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bgColor&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;;
  color: &lt;/span&gt;&lt;span class="p"&gt;${({&lt;/span&gt; &lt;span class="nx"&gt;theme&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;theme&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;color&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;;

  &amp;amp;:hover {
    opacity: 0.9;
    transform: scale(1.02);
  }
`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's go back to &lt;code&gt;App.js&lt;/code&gt; and add our styled button.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;GlobalStyles&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./components/styles/Global&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ThemeProvider&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;styled-components&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;theme&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./components/styles/Theme&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// 👇 Import our new styled component&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;PrimaryButton&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./components/styles/Buttons.styled&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="nx"&gt;App&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="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;ThemeProvider&lt;/span&gt; &lt;span class="nx"&gt;theme&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;theme&lt;/span&gt;&lt;span class="p"&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;GlobalStyles&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;App&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;

        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* 👇 Add an instance of our new button here */&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;PrimaryButton&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;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;You clicked me!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="nx"&gt;Submit&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/PrimaryButton&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/ThemeProvider&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;There we go! We've successfully created our first styled component.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--CBfezUmk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/k3rz5k5q98pr5cgcva6u.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--CBfezUmk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/k3rz5k5q98pr5cgcva6u.gif" alt="Styled Button" width="686" height="382"&gt;&lt;/a&gt;&lt;/p&gt;
Take a look at that button! That's pretty neat!



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

&lt;p&gt;Styled Components is a great tool to have in your toolbelt. As long as you make an appropriate amount of effort to really plan out your reusable components, Styled Components may can help make use of one of Reacts strongest appeals, the use of reusable components.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Photo by rovenimages.com: &lt;a href="https://www.pexels.com/photo/yellow-bokeh-photo-949587/"&gt;https://www.pexels.com/photo/yellow-bokeh-photo-949587/&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>styledcomponents</category>
      <category>react</category>
      <category>webdev</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Rails Validations</title>
      <dc:creator>Nic Mortelliti</dc:creator>
      <pubDate>Tue, 11 Oct 2022 17:56:22 +0000</pubDate>
      <link>https://forem.com/nicm/rails-validations-540m</link>
      <guid>https://forem.com/nicm/rails-validations-540m</guid>
      <description>&lt;h1&gt;
  
  
  Rails Validations Notes
&lt;/h1&gt;

&lt;p&gt;When creating databases, we want our data to be valid, in other words, we expect the data in our database to be of a certain type and format in order to ensure our we can interact with the data in a predictable manner.&lt;/p&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;For example, if we are storing the email addresses of our users, we expect those email addresses to contain certain syntactic features. As &lt;a href="https://www.geekinsta.com/parts-of-an-email-address/"&gt;Mishel Shaji describes&lt;/a&gt;, the email address should contain a username (e.g. "johnsmith"), the @ symbol, the domain name (e.g. "gmail"), a dot (".") and the domain extension (e.g. "edu"). The username, domain name and domain extension must adhere to specific syntactic requirements as determined by the Internet Official Protocol Standards. By the way, if you feel like you need some more technical, non-fiction reading in your life, go check out the Request For Comments (RFC) regarding email address standardization (among other topics) in &lt;a href="https://datatracker.ietf.org/doc/html/rfc5322"&gt;RFC 5322&lt;/a&gt; and &lt;a href="https://datatracker.ietf.org/doc/html/rfc6854"&gt;RFC 6854&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In order to make sure an email address in our database aligns with these standards, we need to use &lt;strong&gt;validation&lt;/strong&gt;. We could, of course, pretend we're fluent in speaking Martian and write a bunch of regex code like that found in this &lt;a href="https://stackoverflow.com/questions/201323/how-can-i-validate-an-email-address-using-a-regular-expression"&gt;StackOverflow answer&lt;/a&gt;:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;(?:[a-z0-9!#$%&amp;amp;'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&amp;amp;'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9]))\.){3}(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9])|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;I'm sure there are completely valid situations where regex is the ideal approach to validation. However, in the case of my Ruby on Rails project with the Flatiron School, Rails' built-in validation macro was the preferred approach.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Thankfully, one of the benefits of developing our back end with Rails is that it has built-in validation tools to do the heavy-lifting, allowing us to keep our code lean and readable.&lt;/p&gt;

&lt;h2&gt;
  
  
  Rails Validations
&lt;/h2&gt;

&lt;p&gt;The &lt;a href="https://guides.rubyonrails.org/active_record_validations.html"&gt;Ruby on Rails guide&lt;/a&gt; describes validations as a way&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;to ensure that only valid data is saved into our database.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Therefore, utilizing Rails validation tools, if our user attempts to create an account with an email address of &lt;code&gt;joe@smith@aol.com&lt;/code&gt;, Rails won't save the new entry into the database because it doesn't adhere to standard email address syntax due to the multiple uses of the "@" symbol.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to include validations in your Rails project
&lt;/h2&gt;

&lt;p&gt;Validations can be included in your Rails project by explicitly using the "validates" keyword in the model, specifying which table attribute is receiving the validation ("email") as well as the type of validations being performed on the attribute ("format", "presence" and "uniqueness").&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;validates&lt;/span&gt; &lt;span class="ss"&gt;:email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;format: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="ss"&gt;with: &lt;/span&gt;&lt;span class="no"&gt;URI&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;MailTo&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;EMAIL_REGEXP&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
                  &lt;span class="ss"&gt;presence: &lt;/span&gt;&lt;span class="kp"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                  &lt;span class="ss"&gt;uniqueness: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="ss"&gt;case_sensitive: &lt;/span&gt;&lt;span class="kp"&gt;false&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  How to handle invalid data
&lt;/h2&gt;

&lt;p&gt;If a validation fails (i.e. returns "invalid"), we can collect all the error messages produced during the validation phase! This is useful, not only to developers during development for debugging, but it's also useful for users of our applications. We can pass the full array of error messages to the front end for display in alert messages, for example.&lt;/p&gt;

&lt;p&gt;Back to our email validation example, we can include our validation error message array in the JSON object we return to the front end like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;render&lt;/span&gt; &lt;span class="ss"&gt;json: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="ss"&gt;errors: &lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;record&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;errors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;full_messages&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="ss"&gt;status: :unauthorized&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, the error messages returned contain the database attribute names (e.g. If no email address is entered and submitted to the API, the "errors" key of the JSON object will contain an array with the message "Email is blank".).&lt;/p&gt;

&lt;p&gt;If our React front end doesn't receive a status of "ok" from the API, we can save the errors to state using the useState hook, then map the error messages to user-facing alerts.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/login&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;"&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="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="nx"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;formData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;password&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;formData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;password&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;}),&lt;/span&gt;
&lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;setIsLoading&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ok&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;onLogin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;setErrors&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;errors&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;h2&gt;
  
  
  What if I don't want to run validations for a particular API action?
&lt;/h2&gt;

&lt;p&gt;It's possible to skip a validation for a particular action. Be careful when doing this, because we may end up saving corrupt or incorrectly formatted data to our database. Check out &lt;a href="https://guides.rubyonrails.org/active_record_validations.html#skipping-validations"&gt;section 1.3 of the Rails Guide on Validations&lt;/a&gt; to learn which methods skip validation.&lt;/p&gt;

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

&lt;p&gt;Rails' built-in validations are great way to reduce the amount of code you need to write in order to ensure you are maintaining a healthy database with predictable data. For more information on Rails validation methods, check out the &lt;a href="https://guides.rubyonrails.org/active_record_validations.html"&gt;Active Record Validations guide&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you've worked on projects involving databases, how does your group handle the validation of data? Are there methods that are pretty standard from organization to organization?&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Including Associated Data In A Sinatra API Response</title>
      <dc:creator>Nic Mortelliti</dc:creator>
      <pubDate>Mon, 18 Jul 2022 18:15:33 +0000</pubDate>
      <link>https://forem.com/nicm/including-associated-data-in-a-sinatra-api-response-4kko</link>
      <guid>https://forem.com/nicm/including-associated-data-in-a-sinatra-api-response-4kko</guid>
      <description>&lt;p&gt;I just wrapped up development on a &lt;a href="https://www.zoho.com/sprints/what-is-a-scrum-board.html"&gt;Scrum&lt;/a&gt;/&lt;a href="https://www.atlassian.com/agile/kanban/boards"&gt;Kanban&lt;/a&gt;-like application based on Ruby and React. In this post, I'll be discussing one of the roadblocks I was up against when creating the Ruby application controller.&lt;/p&gt;




&lt;p&gt;A scrum/kanban (we'll call it scrumban from here on out) board is used by development teams to provide a way to break down a project into smaller chunks of work that are able to be implemented in 2-to-4-week sprints. The scrumban board &lt;em&gt;typically&lt;/em&gt; contains columns for work that is in the backlog, in-progress, in-review and closed.&lt;/p&gt;

&lt;p&gt;My scrumban application allows a team to add new tasks to a project, edit a tasks properties (e.g. description, due date, story points, etc.) and delete tasks. All of the data for this application including users, project names, and tasks reside in their own tables in an SQLite database.&lt;/p&gt;

&lt;p&gt;The scrumban React front end makes HTTP requests to the server through Sinatras application controller. Upon initial page load, the front end makes a request to the server for JSON object containing all of the tasks and their associated project and assigned user. &lt;strong&gt;THIS&lt;/strong&gt; is where I hit a wall during development.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;How do I set up the application controller routing in a way that includes an entities associated data from &lt;strong&gt;multiple&lt;/strong&gt; tables?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--4BjgXk4u--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yxcbzryrtfw6fgfc2zhx.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--4BjgXk4u--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yxcbzryrtfw6fgfc2zhx.gif" alt="Image description" width="480" height="270"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Problem
&lt;/h2&gt;

&lt;p&gt;My Ruby models are set up as shown in the Entity-Relationship Diagram (ERD) shown below. We have a Projects table, a Users table and a Tasks table (our "Join" table). Each task has a single associated project and a single associated user assigned to the task. A project and user can have many tasks.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--1mFnOERJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/np9tlfh9yu74uytzklbe.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--1mFnOERJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/np9tlfh9yu74uytzklbe.png" alt="Scrum Board ERD" width="880" height="479"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When it came time to configure my application controller (the "C" in &lt;a href="https://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller"&gt;MVC&lt;/a&gt;), I wanted to return a JSON object of all of the tasks in the database. I also wanted to include project and user information for each of these tasks. I knew how to access associated data from &lt;strong&gt;one&lt;/strong&gt; table (shown below), but how do I include data from &lt;strong&gt;multiple&lt;/strong&gt; tables?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="n"&gt;get&lt;/span&gt; &lt;span class="s1"&gt;'/'&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
&lt;span class="mi"&gt;2&lt;/span&gt;   &lt;span class="n"&gt;task&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;
&lt;span class="mi"&gt;3&lt;/span&gt;   &lt;span class="n"&gt;task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to_json&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;span class="mi"&gt;4&lt;/span&gt;     &lt;span class="ss"&gt;include: :project&lt;/span&gt;
&lt;span class="mi"&gt;5&lt;/span&gt;   &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="mi"&gt;6&lt;/span&gt; &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I searched forums and read the Sinatra documentation, but I just couldn't find the solution. I'm sure the answer &lt;strong&gt;is&lt;/strong&gt; documented out there somewhere. But I was struggled to find it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Solution
&lt;/h2&gt;

&lt;p&gt;One day I decided I was going to solve the mystery once and for all. I refused to build work-arounds into the client-side React application (e.g. multiple fetch requests, filtering arrays to find matching foreign and local keys, etc).&lt;/p&gt;

&lt;p&gt;I threw everything I had at the problem. I tried multiple &lt;code&gt;include:&lt;/code&gt; statements. I tried putting putting the associated tables into an object like this &lt;code&gt;include: {:project, :user}&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Finally, I tried an array. It worked! Putting &lt;code&gt;[:project, :user]&lt;/code&gt; after the &lt;code&gt;include:&lt;/code&gt; statement is we include associated data from multiple tables!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="n"&gt;get&lt;/span&gt; &lt;span class="s1"&gt;'/'&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
&lt;span class="mi"&gt;2&lt;/span&gt;   &lt;span class="n"&gt;task&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;
&lt;span class="mi"&gt;3&lt;/span&gt;   &lt;span class="n"&gt;task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to_json&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;span class="mi"&gt;4&lt;/span&gt;     &lt;span class="ss"&gt;include: &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:project&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:user&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="mi"&gt;5&lt;/span&gt;   &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="mi"&gt;6&lt;/span&gt; &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--onYcW8YZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ye9poqfor684ov00zk78.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--onYcW8YZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ye9poqfor684ov00zk78.gif" alt="Image description" width="480" height="269"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This will now give us the associated project &lt;strong&gt;and&lt;/strong&gt; the assigned user for each task! It seems so simple now, but I was truly at a loss.&lt;/p&gt;

&lt;p&gt;I hope this post helps someone else. If it does, let me know in the comments!&lt;/p&gt;

&lt;p&gt;Photo by &lt;a href="https://unsplash.com/@joshuafuller?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Joshua Fuller&lt;/a&gt; on &lt;a href="https://unsplash.com/s/photos/ruby?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ruby</category>
      <category>beginners</category>
      <category>webdev</category>
      <category>sinatra</category>
    </item>
    <item>
      <title>React useEffect Dependency Warnings?!</title>
      <dc:creator>Nic Mortelliti</dc:creator>
      <pubDate>Sat, 14 May 2022 22:33:34 +0000</pubDate>
      <link>https://forem.com/nicm/react-useeffect-dependency-warnings-jkf</link>
      <guid>https://forem.com/nicm/react-useeffect-dependency-warnings-jkf</guid>
      <description>&lt;p&gt;I'm nearing the end of phase 2 of the Flatiron Software Engineering bootcamp. React was the focus of this phase and, honestly, it was a lot of fun. I really enjoyed learning about props, states, events, controlled components, side effects, client-side routing, etc. However, there was one area of React that was causing some confusion for me... ESLint kept warning me of missing dependencies when using the useEffect hook.&lt;/p&gt;

&lt;h2&gt;
  
  
  useEffect
&lt;/h2&gt;

&lt;p&gt;The useEffect hook allows us to call a function that is passed into it whenever a component renders. To prevent the function from being called with every render (e.g. when we want to fetch data from an API only once), we provide useEffect with a dependencies array.&lt;/p&gt;

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

&lt;p&gt;In the example above, I'm providing the useEffect hook with an empty array as its dependency. This tells React that it only needs to run this function once.&lt;/p&gt;

&lt;h2&gt;
  
  
  ESLint Dependency Warning
&lt;/h2&gt;

&lt;p&gt;If, however, our function inside the useEffect hook contains props and/or states, we need to add these as dependencies within the dependency array.&lt;/p&gt;

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

&lt;p&gt;In this example, notice that I'm only including the "currentAircraft" state as the sole dependency. This is all React requires us to include. The setter function "setCurrentAircraft" isn't a state or a prop, it's a function and therefore, is not a dependency. However, ESLint will underline the depenedency array with the message &lt;code&gt;React Hook useEffect has a missing dependency: 'setCurrentAircraft'. Either include it or remove the dependency&lt;/code&gt;. It doesn't hurt to include the setter function as a dependency to appease the warning. But I wanted to find a better solution.&lt;/p&gt;

&lt;p&gt;After some forum and documentation searching, I found a great solution in this &lt;a href="https://stackoverflow.com/questions/61711085/why-react-expects-me-to-add-setters-as-useeffects-dependencies"&gt;stack overflow post&lt;/a&gt;. In the highest scoring solution, Shubham Khatri recommends adding the &lt;code&gt;eslint-disable-next-line&lt;/code&gt; comment above the dependencies line. So our example above would now look like this:&lt;/p&gt;

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

&lt;p&gt;Reading through the ESLint github, it seems that ESLint isn't able to determine if a dependency is a setter function. At least not yet. Therefore, this workaround is necessary if you dislike the nagging of false warnings. I suppose you could just ignore the warning :)&lt;/p&gt;

&lt;p&gt;If you have a different way to deal with this warning, or my interpretation of the warning is a little off, please let me know in the comments! After all, I'm no React expert... yet.&lt;/p&gt;

&lt;p&gt;Photo by &lt;a href="https://unsplash.com/@lautaroandreani?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Lautaro Andreani&lt;/a&gt; on &lt;a href="https://unsplash.com/s/photos/react?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;

</description>
      <category>react</category>
      <category>codenewbie</category>
      <category>webdev</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Bored? Try my first app!</title>
      <dc:creator>Nic Mortelliti</dc:creator>
      <pubDate>Sun, 13 Mar 2022 01:12:27 +0000</pubDate>
      <link>https://forem.com/nicm/bored-try-my-first-app-18fi</link>
      <guid>https://forem.com/nicm/bored-try-my-first-app-18fi</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Here we are at the end of phase 1 of the Flatiron School Full-Stack Development bootcamp. It was a rocky start with the holiday break followed by two weeks of daycare closures due to covid. But I've finally made it to the end of phase 1 where the main focus was on HTML, CSS and a lot of Javascript.&lt;/p&gt;

&lt;h2&gt;
  
  
  Requirements
&lt;/h2&gt;

&lt;p&gt;The basic requirements of the project were as follows:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;An HTML/CSS/JS frontend that accesses data, asynchronously, from an API of our choosing&lt;/li&gt;
&lt;li&gt;Must be a single-page app&lt;/li&gt;
&lt;li&gt;Must contain at least 3 separate event listeners (e.g. content load completion, mouse click, etc)&lt;/li&gt;
&lt;li&gt;Some user interactivity&lt;/li&gt;
&lt;li&gt;Follow good coding practices&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  This is borrrinnngg
&lt;/h2&gt;

&lt;p&gt;Since my 4-year-old has been going around the house saying "This is borrringgg" I thought it was fitting to utilize the API from boredapi.com. This API will return a random activity from its database based on the criteria sent to it via fetch from JavaScript.&lt;/p&gt;

&lt;p&gt;The app allows the user to make selections in regards to activity type (e.g. educational, social, recreational, etc.), the number of people to participate in the activity and if the activity needs to be free. A couple of functions packages up these selections and sends it to the API via JavaScripts Fetch "Get" command. If an activity is found with the users search criteria, it is returned to us within a JSON-formatted message.&lt;/p&gt;

&lt;p&gt;The app then parses this message and specifically looks at three key-value pairs within the message:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Error - An error is returned if the API cannot find an activity with the given search criteria. In this case, an alert message is shown instructing the user to change their search criteria.&lt;/li&gt;
&lt;li&gt;Activity - This gives us the activity suggestion returned by the API (e.g. "Organize your basement".... no thanks). The activity string is displayed prominently below the Submit button.&lt;/li&gt;
&lt;li&gt;URL - Most activity suggestions don't include a URL. However, if one is included, the displayed activity string contains the provided URL, allowing the user easy access to the related article.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If the user repeatedly clicks the Submit button, a history of the 5 most recent activity ideas is displayed underneath the current activity idea. A Clear button is provided with the history list to tidy things up...and to get me my third event listener 😉.&lt;/p&gt;

&lt;h3&gt;
  
  
  DOM Manilpulation
&lt;/h3&gt;

&lt;p&gt;So far, one of my favorite parts about web development, specifically with JavaScript, is DOM manipulation. How cool is it that you can basically create an entire web page dynamically with minimal static HTML? Well, I think it's pretty cool. I made sure to use this approach at least once in this app.&lt;/p&gt;

&lt;p&gt;The Clear button is an example of DOM manipulation. When the app first loads, the Clear button doesn't even exist in the HTML yet. However, once the history list starts to populate, I create a brand new button element. The following is an example of the code I used to accomplish this.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Ya_Cisvj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/x1mcp37env4d2l7zbz5e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Ya_Cisvj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/x1mcp37env4d2l7zbz5e.png" alt="DOM Manipulation Example" width="880" height="252"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Arrow Functions
&lt;/h3&gt;

&lt;p&gt;Another favorite of mine is the arrow function. I love the simplicity and efficiency of an arrow function. &lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--NRsbIs1Z--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1zdeqc0b2mak5hxpkbju.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--NRsbIs1Z--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1zdeqc0b2mak5hxpkbju.png" alt="Arrow Function Example" width="880" height="255"&gt;&lt;/a&gt;&lt;br&gt;
The Arrow Function is simple in that it’s easy to read. The arrow literally shows the argument of the function going into the body of the function. &lt;/p&gt;

&lt;p&gt;It’s efficient because it doesn’t waste as much space as a normal function. You can literally fit an entire function, arguments, body and all, on one line of code!&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping up
&lt;/h2&gt;

&lt;p&gt;It’s been a lot fun putting all of my new skills to use and creating something I can be proud of. Although simple in nature and execution, the app is a culmination of the skills I’ve accumulated in just a couple of months. There are 4 phases of the bootcamp left. I can’t wait to see what I can create at the end of the next phase and the phase after that…&lt;/p&gt;

&lt;p&gt;Please feel free to check it out here and provide feedback:&lt;br&gt;
&lt;a href="https://nicmortelliti.github.io/Bored/"&gt;https://nicmortelliti.github.io/Bored/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The project can be cloned here:&lt;br&gt;
&lt;a href="https://github.com/NicMortelliti/Bored"&gt;https://github.com/NicMortelliti/Bored&lt;/a&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>bootcamp</category>
      <category>codenewbie</category>
    </item>
    <item>
      <title>Here we go!</title>
      <dc:creator>Nic Mortelliti</dc:creator>
      <pubDate>Fri, 04 Mar 2022 03:58:35 +0000</pubDate>
      <link>https://forem.com/nicm/here-we-go-17fa</link>
      <guid>https://forem.com/nicm/here-we-go-17fa</guid>
      <description>&lt;p&gt;Hey! Welcome to my blog! Not much to see here yet, but I intend for this to be my platform for journaling my formal journey into the Full-Stack development world with the Flatiron school.&lt;/p&gt;

&lt;p&gt;My name is Nic and I live in the beautiful Pacific Northwest with my wife and two daughters. I love traveling, photography, road trips, flying airplanes, music, food and, of course, anything technology related.&lt;/p&gt;

&lt;p&gt;I recently left my career of 10+ years as a Systems Engineer in the aviation industry to pursue my interests in coding and web development. During that time I found myself playing around with Raspberry Pi’s, microcontrollers and self-hosting smart home services (thanks HomeAssistant!).&lt;/p&gt;

&lt;p&gt;Thanks for reading!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>codenewbie</category>
      <category>bootcamp</category>
    </item>
  </channel>
</rss>
