<?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: Ryan Lanciaux</title>
    <description>The latest articles on DEV Community by Ryan Lanciaux (@ryanlanciaux).</description>
    <link>https://dev.to/ryanlanciaux</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%2F34114%2Fcf821a04-560b-42d3-8ff1-3646e5e62261.jpeg</url>
      <title>DEV Community: Ryan Lanciaux</title>
      <link>https://dev.to/ryanlanciaux</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ryanlanciaux"/>
    <language>en</language>
    <item>
      <title>AI Generating a 3d Print</title>
      <dc:creator>Ryan Lanciaux</dc:creator>
      <pubDate>Mon, 09 Dec 2024 18:27:25 +0000</pubDate>
      <link>https://dev.to/ryanlanciaux/ai-generating-a-3d-print-2e76</link>
      <guid>https://dev.to/ryanlanciaux/ai-generating-a-3d-print-2e76</guid>
      <description>&lt;p&gt;Quickly take an AI generated image and make it a 3d print with the following steps.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Generate an image&lt;/li&gt;
&lt;li&gt;Make the image a 3d model&lt;/li&gt;
&lt;li&gt;Translate the model to something 3d printer software understands&lt;/li&gt;
&lt;li&gt;Print (after coloring the model &lt;em&gt;optional&lt;/em&gt;)&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Generate an image
&lt;/h2&gt;

&lt;p&gt;Use &lt;a href="https://replicate.com/black-forest-labs/flux-1.1-pro-ultra" rel="noopener noreferrer"&gt;Flux&lt;/a&gt; or some other image generator to create an image. Be sure to include something like "Video game concept art pure white background" or "bright green background" to have the ability to remove the background easily. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2F7o1fy9wp5ldxrjbeaews.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2F7o1fy9wp5ldxrjbeaews.png" alt="Generated image" width="680" height="453"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Use Convert the image to a 3d model
&lt;/h2&gt;

&lt;p&gt;I used &lt;a href="https://huggingface.co/spaces/JeffreyXiang/TRELLIS" rel="noopener noreferrer"&gt;TRELLIS&lt;/a&gt; to generate a 3d model from my image. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fr3lrkscpg9grp4ayau9u.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fr3lrkscpg9grp4ayau9u.png" alt="TRELLIS" width="800" height="429"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Translate the model to something a 3d printer can understand
&lt;/h2&gt;

&lt;p&gt;Most slicer software needs stl or 3mf (although many can import from other file types). You can use a tool like &lt;a href="https://imagetostl.com/convert/file/glb/to/stl#convert" rel="noopener noreferrer"&gt;Image-to-STL&lt;/a&gt; or open in Blender and export as STL/3mf. &lt;/p&gt;

&lt;h2&gt;
  
  
  Print the Model
&lt;/h2&gt;

&lt;p&gt;Now you should be ready to print your model. I re-colored it in Bambu Studio, as I wasn't able to figure out a way to keep the colors intact through the filetype translation process. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2F8we3hq20lz7lxgqcbg7n.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2F8we3hq20lz7lxgqcbg7n.png" alt="Penguin in Bambu Studio" width="800" height="517"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And the result&lt;br&gt;
&lt;a href="https://media2.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%2Fejz3afuirtqbpg8bjn6o.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fejz3afuirtqbpg8bjn6o.png" alt="Printed result" width="800" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let me know what you think.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>3dprinting</category>
      <category>3dmodel</category>
      <category>imadethis</category>
    </item>
    <item>
      <title>A couple tips for working from home</title>
      <dc:creator>Ryan Lanciaux</dc:creator>
      <pubDate>Wed, 05 Aug 2020 12:22:19 +0000</pubDate>
      <link>https://dev.to/ryanlanciaux/a-couple-tips-for-working-from-home-43mh</link>
      <guid>https://dev.to/ryanlanciaux/a-couple-tips-for-working-from-home-43mh</guid>
      <description>&lt;p&gt;Many developers have been tossed into remote work due to the pandemic. While it's quite a lot different than what remote work is like without an epidemic, it's great that technology allows developers to work while staying safe. &lt;/p&gt;

&lt;p&gt;I've been working remotely in some capacity for over seven years. A couple of things I try to do to help remote work go as smoothly as possible:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Communicate A LOT but in the right medium&lt;/strong&gt;
e.g. Don't send a giant feature proposal over your messaging client. My rule of thumb here, if it's something that needs to be referenced later, it goes into something less timeline based (JIRA / Confluence / Docs / whatever)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Eliminate distractions&lt;/strong&gt;
If you have a personality where you get side-tracked easily, put your phone in another room. Use tools to help you block sites that you waste time on, etc.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Write down your daily goals and execute on them&lt;/strong&gt;
Some people do this by creating personal calendar invites for their tasks, TODO lists, or writing things down in notebooks. I do a combination of TODO lists + calendar items for tasks. It's okay if things need to change but writing down your goals is an excellent way to be mindful that you're changing your goals intentionally, instead of drifting into what you focus on. &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;If possible, keep your work equipment in another room&lt;/strong&gt;
I totally get it's not possible for everyone, but I find it helpful to have a space where I use my work equipment and &lt;em&gt;mostly&lt;/em&gt; use it only in that space. This helps me keep some boundaries between when I'm working and not.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Get outside (if possible)&lt;/strong&gt;
I like to both take walks and otherwise exercise. I notice on the days I do this I'm both more productive, and generally feel better.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I'd love to hear your tips in the comments or on the following Twitter thread. Be sure to check out the thread for more:&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1236298297532452865-314" src="https://platform.twitter.com/embed/Tweet.html?id=1236298297532452865"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1236298297532452865-314');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1236298297532452865&amp;amp;theme=dark"
  }



&lt;/p&gt;

</description>
      <category>watercooler</category>
      <category>productivity</category>
      <category>remote</category>
      <category>tips</category>
    </item>
    <item>
      <title>Add a visitor count on your GitHub profile with one line of Markdown</title>
      <dc:creator>Ryan Lanciaux</dc:creator>
      <pubDate>Thu, 16 Jul 2020 14:04:41 +0000</pubDate>
      <link>https://dev.to/ryanlanciaux/visitor-count-on-your-github-profile-with-one-line-of-markdown-593g</link>
      <guid>https://dev.to/ryanlanciaux/visitor-count-on-your-github-profile-with-one-line-of-markdown-593g</guid>
      <description>&lt;p&gt;In &lt;a href="https://dev.to/ryanlanciaux/quick-github-profile-visit-counter-14en"&gt;a previous article, I wrote about how you could add a visitor counter to your GitHub profile with a little node/express app&lt;/a&gt;. The article suggested that if you wanted to add a counter to your GitHub profile, you could copy and run the code on your own server. I've recently updated this operation to be a lot easier.&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1283755637126705152-380" src="https://platform.twitter.com/embed/Tweet.html?id=1283755637126705152"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1283755637126705152-380');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1283755637126705152&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;p&gt;You can now add a counter to your GitHub profile with the following line of Markdown&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;![Visitor Count](https://profile-counter.glitch.me/{YOUR USER}/count.svg)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I'd love to know what you think!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>watercooler</category>
    </item>
    <item>
      <title>Quick GitHub profile visit counter</title>
      <dc:creator>Ryan Lanciaux</dc:creator>
      <pubDate>Mon, 13 Jul 2020 13:05:44 +0000</pubDate>
      <link>https://dev.to/ryanlanciaux/quick-github-profile-visit-counter-14en</link>
      <guid>https://dev.to/ryanlanciaux/quick-github-profile-visit-counter-14en</guid>
      <description>&lt;h2&gt;
  
  
  UPDATE:
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;h2&gt;
  
  
  For those that don't want to run their own server, be sure to &lt;a href="https://dev.to/ryanlanciaux/visitor-count-on-your-github-profile-with-one-line-of-markdown-593g"&gt;check out a quick guide to add a visitor counter with one line of markdown&lt;/a&gt;.
&lt;/h2&gt;
&lt;/blockquote&gt;

&lt;p&gt;GitHub profiles are a great addition to the platform. These profiles allow you to highlight your experience/interests and supply a little bit of personality to what people see when they visit your profile. There are quite a few guides on creating a profile, but for those who may not have jumped into that just yet, you can add your profile by creating a new repository that matches your GitHub username. Any edits to the README.md file will show up when people vist github.com/{your_user_name}&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fjbi0xsunc3bij6965pom.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fjbi0xsunc3bij6965pom.png" alt="Create GitHub profile" width="590" height="174"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Website Counter
&lt;/h2&gt;

&lt;p&gt;I wanted to see if I could make my profile look a little bit like a website from the 1990s. A big part of any 90s personal website is the visitor counter. We can create a fun (and not necessarily accurate) counter pretty quickly using node and express. I ended up using Glitch for mine, but this concept should work on any platform that supports node. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fm2pif8edxgvyb8b81haj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fm2pif8edxgvyb8b81haj.png" alt="Counter example" width="368" height="102"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/ryanlanciaux" rel="noopener noreferrer"&gt;Take a look at my GitHub profile to see this in action&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Node / Express project
&lt;/h2&gt;

&lt;p&gt;The entire code for this project is posted below (or in &lt;a href="https://gist.github.com/ryanlanciaux/3e29e75bd32efee9681c2ab85b99cc6f" rel="noopener noreferrer"&gt;this GitHub gist&lt;/a&gt;, or where it's running &lt;a href="https://glitch.com/edit/#!/ryan-lanciaux-counter?path=server.js%3A1%3A0" rel="noopener noreferrer"&gt;on Glitch&lt;/a&gt;). There are a lot of practices that we'd either want to avoid or clean up if it was for more of a production application. The key here is something that could be accomplished quickly for fun.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tracking visits
&lt;/h2&gt;

&lt;p&gt;From a high level, this application has a variable that records visit counts, an endpoint that responds to count.svg and updates the visit counts. Additionally, the count.svg endpoint should generate and respond with an image based on the count.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const express = require('express')
const app = express()

const PLACES = 7;

// no db - so global var to keep track of count
let counter = 0

function getCountImage(count) {
   ...
}

// get the image
app.get('/count.svg', (req, res) =&amp;gt; {
  counter++;

  // This helps with GitHub's image cache 
  //   see more: https://rushter.com/counter.svg
  res.set({
  'content-type': 'image/svg+xml',
  'cache-control': 'max-age=0, no-cache, no-store, must-revalidate'
  })

  // Send the generated SVG as the result
  res.send(getCountImage(counter));
})

const listener = app.listen(process.env.PORT, () =&amp;gt; {
  console.log('Your app is listening on port ' + listener.address().port)
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Tracking visit count
&lt;/h2&gt;

&lt;p&gt;We're using the global counter variable to keep track of visits. When a request comes in to count.svg, we update the global counter variable and generate an image.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// set up the counter variable
let counter = 0;

...
app.get('/count.svg', (req, res) =&amp;gt; {
  // update the counter on any image request
  counter++;
  ...
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Generating an image
&lt;/h2&gt;

&lt;p&gt;I created an image in Sketch and copied the results as SVG and pasted it into the &lt;code&gt;getCountImage&lt;/code&gt; method. The image was dissected a bit and rebuilt using our count value.&lt;/p&gt;

&lt;p&gt;You'll notice in this function, we're switching the count to a padded string, and then into an array. This allows us to show the zeros before the count with the specified number of PLACES. &lt;code&gt;const countArray = count.toString().padStart(PLACES, '0').split('');&lt;/code&gt; From there, we build the count squares part of the image by reducing the array into a single string, and then referencing that in the svg.&lt;/p&gt;

&lt;p&gt;Reduce can be a bit tricky to follow at times, and could often be replaced by a more standard loop construct. In this case, we're saying, iterate through all the array elements and append this new svg section with what came before.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function getCountImage(count) {
  // This is not the greatest way for generating an SVG but it'll do for now
  const countArray = count.toString().padStart(PLACES, '0').split('');

  const parts = countArray.reduce((acc, next, index) =&amp;gt; `
        ${acc}
        &amp;lt;rect id="Rectangle" fill="#000000" x="${index * 32}" y="0.5" width="29" height="29"&amp;gt;&amp;lt;/rect&amp;gt;
        &amp;lt;text id="0" font-family="Courier" font-size="24" font-weight="normal" fill="#00FF13"&amp;gt;
            &amp;lt;tspan x="${index * 32 + 7}" y="22"&amp;gt;${next}&amp;lt;/tspan&amp;gt;
        &amp;lt;/text&amp;gt;
`, '');

  return `&amp;lt;?xml version="1.0" encoding="UTF-8"?&amp;gt;
&amp;lt;svg width="${PLACES * 32}px" height="30px" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"&amp;gt;
    &amp;lt;title&amp;gt;Count&amp;lt;/title&amp;gt;
    &amp;lt;g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd"&amp;gt;
      ${parts}
    &amp;lt;/g&amp;gt;
&amp;lt;/svg&amp;gt;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;Ideally, we would want to persist our count to ensure that if the server restarts, the count values picks back up where we left off. &lt;br&gt;
This could be something like a database record, or simply writing to a file. For this example, I don't care too much if I lose the count as it's mostly to achieve the 90s design aesthetics :D &lt;/p&gt;

&lt;p&gt;The full code is available in &lt;a href="https://gist.github.com/ryanlanciaux/3e29e75bd32efee9681c2ab85b99cc6f" rel="noopener noreferrer"&gt;this GitHub gist&lt;/a&gt;, or where it's running &lt;a href="https://glitch.com/edit/#!/ryan-lanciaux-counter?path=server.js%3A1%3A0" rel="noopener noreferrer"&gt;on Glitch&lt;/a&gt;. &lt;/p&gt;

&lt;h2&gt;
  
  
  Additional references:
&lt;/h2&gt;

&lt;p&gt;I started off referencing &lt;a href="https://flaviocopes.com/count-visits-static-site/" rel="noopener noreferrer"&gt;an analytics example by Flavio Copes&lt;/a&gt; available here. In this example, Flavio created an svg that would collect website visit counts as a simple alternative to Google Analytics.  &lt;/p&gt;

&lt;p&gt;This &lt;a href="https://rushter.com/blog/github-profile-markdown/" rel="noopener noreferrer"&gt;article on the same topic by Artem Golubin&lt;/a&gt; was really helpful in determining how to adjust the HTTP headers to work with GitHub's image caching. &lt;a href="https://docs.github.com/en/github/authenticating-to-github/about-anonymized-image-urls" rel="noopener noreferrer"&gt;GitHub has an excellent feature that anonymizes browser details from images to help prevent tracking called Camo&lt;/a&gt;. Without adjusting the HTTP headers, the image would not update upon new visits.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>node</category>
      <category>github</category>
    </item>
    <item>
      <title>Better testing with Storybook</title>
      <dc:creator>Ryan Lanciaux</dc:creator>
      <pubDate>Fri, 14 Feb 2020 19:57:08 +0000</pubDate>
      <link>https://dev.to/ryanlanciaux/better-testing-with-storybook-3fn</link>
      <guid>https://dev.to/ryanlanciaux/better-testing-with-storybook-3fn</guid>
      <description>&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/C3UrkCVulaE"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;In this article, we will discuss strategy that I like to help keep &lt;a href="https://storybook.js.org/" rel="noopener noreferrer"&gt;Storybook&lt;/a&gt; stories up-to-date. For those that are unfamiliar, &lt;a href="https://storybook.js.org/" rel="noopener noreferrer"&gt;Storybook&lt;/a&gt; is a UI component workspace that I find helpful in building front-end applications.&lt;/p&gt;

&lt;p&gt;It allows you to develop your components in isolation, interact with these components individually, and see quality issues at a much more granular level than the screen or page level. Additionally, this workspace serves as communication to other developers, noting the reusable components that exist in a system. &lt;a href="https://storybook.js.org/" rel="noopener noreferrer"&gt;Learn more about Storybook here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;One criticism I often hear is that it's easy for a &lt;a href="https://storybook.js.org/" rel="noopener noreferrer"&gt;Storybook&lt;/a&gt; project to get out-of-date when developers forget to add their components to Storybook. I often find that Storybook speeds up development but understand the tendency to build new components in the context of the live, running application. It's easy to forget about adding stories when you have an otherwise working and tested feature.&lt;/p&gt;

&lt;p&gt;How do we keep this "building components in isolation" mindset top-of-mind in a way that provides immediate value to others may not necessarily develop their components in Storybook first? In this scenario, I often like to treat stories as part of my testing strategy.&lt;/p&gt;

&lt;h2&gt;
  
  
  Traditional Testing
&lt;/h2&gt;

&lt;p&gt;Let's assume we are building an activity feed. On our activity feed item component, we want to ensure that we're rendering the correct text, and the button onClick event fires as expected. We could use &lt;a href="https://testing-library.com/docs/react-testing-library/intro" rel="noopener noreferrer"&gt;react-testing-library&lt;/a&gt; to establish confidence that our component is working as anticipated.&lt;/p&gt;

&lt;p&gt;We'll use the &lt;code&gt;render&lt;/code&gt; utility to render the component that we wish to test. We'll check the text and onClick functionality to ensure that everything is working.&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="c1"&gt;// ActivityFeedItem.js&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;ActivityFeedItem&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;text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;onClick&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;Card&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;Heading&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;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/Heading&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;Text&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;text&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;/Text&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;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;onClick&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;See&lt;/span&gt; &lt;span class="nx"&gt;Details&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/Button&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;/Card&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="c1"&gt;// ActivityFeedItem.test.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;render&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;@testing-library/react&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="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;shows the correct text&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;getByText&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;render&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;ActivityFeedItem&lt;/span&gt;
      &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;This is the heading!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
      &lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Nostrud tempor ullamco aute nostrud commodo cillum amet ad velit veniam officia minim.&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="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nf"&gt;getByText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Nostrud tempor ullamco aute nostrud commodo cillum amet ad velit veniam officia minim.&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="nf"&gt;toBeInTheDocument&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;When we run our tests, we'll see that all is working as expected.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Test Suites: 7 passed, 7 total
Tests:       9 passed, 9 total
Snapshots:   5 passed, 5 total
Time:        2.62s
Ran all test suites.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Debugging failing tests
&lt;/h2&gt;

&lt;p&gt;What happens if our test is failing, and we want to dive in to debug?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Test Suites: 1 failed, 6 passed, 7 total
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There are a couple of options but, one I use a lot is the &lt;code&gt;debug&lt;/code&gt; utility from React testing library. This utility illuminates the HTML for the rendered element.&lt;/p&gt;

&lt;p&gt;We could update our test as follows to leverage &lt;code&gt;debug&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;getByText&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;debug&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;render&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;ActivityFeedItem&lt;/span&gt;
    &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;This is the heading!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
    &lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Sit enim irure pariatur nostrud id non deserunt laboris veniam velit.&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="nf"&gt;debug&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;debug&lt;/code&gt; utility will log the HTML for our components. This strategy would work well for our trivial example component, but on a more substantial component, this can get unwieldy pretty quickly.&lt;/p&gt;

&lt;p&gt;Instead of defining our elements to render directly in our test, we can leverage Storybook stories for this. We'll use stories written in Storybook's &lt;a href="https://storybook.js.org/docs/formats/component-story-format/" rel="noopener noreferrer"&gt;component story format&lt;/a&gt; to serve as the element we wish to &lt;code&gt;render&lt;/code&gt; in our test.&lt;/p&gt;

&lt;p&gt;We'll create the story metadata first. This metadata provides information to Storybook about how we should display our stories within the utility. Next, we'll create a story with the component story format. You may notice that we're creating an arrow function, which is not unique to Storybook. We can export this arrow function and import it in our test.&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="c1"&gt;// ActivityFeedItem.stories.js&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ActivityFeedItem&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;standard&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;callback&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;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;ActivityFeedItem&lt;/span&gt;
      &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;This is the heading&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
      &lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Nostrud tempor ullamco aute nostrud commodo cillum amet ad velit veniam officia minim.&lt;/span&gt;&lt;span class="dl"&gt;"&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;callback&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Using the story in our test
&lt;/h2&gt;

&lt;p&gt;Before where we &lt;code&gt;rendered&lt;/code&gt; our component in the test, we'll use the imported story instead. Now, if we want to debug our test, we have a story we can use in addition to the other debugging strategies we may traditionally use.&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;standard&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;./ActivityFeedItem.stories&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;

&lt;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;shows the correct text&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;getByText&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;standard&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;

  &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nf"&gt;getByText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Nostrud tempor ullamco aute nostrud commodo cillum amet ad velit veiam officia minim.&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="nf"&gt;toBeInTheDocument&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://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/http%3A%2F%2Fryanlanciaux.com%2Fstatic%2F2aa3e8498ba60f9ce0baef438f4a5da6%2Fc6ee2%2Fstorybook_output.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/http%3A%2F%2Fryanlanciaux.com%2Fstatic%2F2aa3e8498ba60f9ce0baef438f4a5da6%2Fc6ee2%2Fstorybook_output.png" alt="Storybook view of component" width="800" height="369"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We now have a way to visualize and interact with the component we're testing.&lt;/p&gt;

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

&lt;p&gt;Storybook provides many benefits beyond testing, but sometimes it's easy to forget when we're trying to get features out the door. I've found that using Storybook as a tool to help ensure quality helps avoid this situation where stories become out-of-date or neglected.&lt;/p&gt;

</description>
      <category>react</category>
      <category>webdev</category>
      <category>testing</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Optional Chaining in JavaScript</title>
      <dc:creator>Ryan Lanciaux</dc:creator>
      <pubDate>Fri, 31 Jan 2020 07:15:03 +0000</pubDate>
      <link>https://dev.to/ryanlanciaux/optional-chaining-in-javascript-56ih</link>
      <guid>https://dev.to/ryanlanciaux/optional-chaining-in-javascript-56ih</guid>
      <description>&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/u90I9BuOcmE"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;In this article, we're going to take a quick look at the new, Optional Chaining operator in JavaScript. This language feature is valid JavaScript as of ES 2020 (the official definition of the language).&lt;/p&gt;

&lt;p&gt;To take a look at why I think this feature is compelling, let's assume we have an object that represents a menu for a conference meal plan. Each object represents a different day for the conference and each day can have &lt;code&gt;breakfast&lt;/code&gt;, &lt;code&gt;lunch&lt;/code&gt;, and &lt;code&gt;dinner&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const monday = {
  menuItems: {
    breakfast: {
      items: ['Eggs', 'Oatmeal', 'Cereal']
    },
    lunch: {
      items: ['Sandwich']
    },
    dinner: {
      items: ['Cheeseburger', 'Salads', 'Tempeh Sandwich']
    }
  }
};

const tuesday = {
  menuItems: {
    breakfast: {
      items: ['Cereal', 'Bagel']
    },
    dinner: {
      items: ['Tacos']
    }
  }
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For our example, we'd like to &lt;code&gt;console.log&lt;/code&gt; the first element of the lunch object. We'll display "No lunch on this day" for any day where lunch is not specified (and therefore not provided). We'll start with the following code.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function logLunch(day) {
  const lunchItem = day.menuItems.lunch.items[0];

  console.log(lunchItem || "No lunch on this day");
}


logLunch(monday);
logLunch(tuesday);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This function works well for Monday, but fails for the Tuesday object since it only specifies a &lt;code&gt;breakfast&lt;/code&gt; and &lt;code&gt;dinner.&lt;/code&gt; Typically we could solve that by ensuring our properties exist before interacting with them. In this case, our expression could look something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const lunchItem = day &amp;amp;&amp;amp; day.menuItems &amp;amp;&amp;amp; day.menuItems.lunch &amp;amp;&amp;amp; day.menuItems.lunch.items &amp;amp;&amp;amp; day.menuItems.lunch.items[0]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It's not very pleasant to guard each property like this!&lt;/p&gt;

&lt;h2&gt;
  
  
  Optional Chaining
&lt;/h2&gt;

&lt;p&gt;Thankfully, we can rewrite this line with Optional Chaining to the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const lunchItem = day?.menuItems?.lunch?.items[0];
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We're using the &lt;code&gt;?.&lt;/code&gt; instead of a &lt;code&gt;.&lt;/code&gt; between properties. This &lt;code&gt;?.&lt;/code&gt; is the &lt;code&gt;optional chaining&lt;/code&gt; operator. This entire expression will be evaluated as undefined if any of the properties are null or undefined. Instead of checking these properties, we can express the desired intent much more cleanly with this new operator.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://codepen.io/ryanlanciaux/pen/KKwLBYp?editors=0012" rel="noopener noreferrer"&gt;Check out the example for this article on Codepen&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I'd love to know of any thoughts you have. You can &lt;a href="https://twitter.com/ryanlanciaux" rel="noopener noreferrer"&gt;find me on Twitter here&lt;/a&gt;!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>tutorial</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Nullish Coalescing in JavaScript</title>
      <dc:creator>Ryan Lanciaux</dc:creator>
      <pubDate>Wed, 22 Jan 2020 07:15:03 +0000</pubDate>
      <link>https://dev.to/ryanlanciaux/nullish-coalescing-in-javascript-4bim</link>
      <guid>https://dev.to/ryanlanciaux/nullish-coalescing-in-javascript-4bim</guid>
      <description>&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/CJWFr6VJ_A4"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Nullish Coalescing is a language feature of JavaScript that was recently promoted to Stage 4 by TC39, the group that maintains the definition of JavaScript. This means that this language feature is valid JavaScript as of ES2020.&lt;/p&gt;

&lt;p&gt;With any language feature, it's good to understand how it helps us. Nullish Coalescing helps us eliminate a certain class of code that primarily consists of checking if something is null or undefined.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://codepen.io/ryanlanciaux/pen/YzPdbLv?editors=0010" rel="noopener noreferrer"&gt;Lets take an example where we want to display a Star Wars character's first and last name&lt;/a&gt;. When the last name is undefined, we should show "Not Specified", but if the last name is "" we should treat it like the character doesn't have a last name. (noting that if this was not example code we would probably want to implement different logic for this)&lt;/p&gt;

&lt;p&gt;For instance, if we had the following character definitions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const hanSolo = {
  first: 'Han',
  last: "Solo"
};

const chewbacca = {
  first: "Chewbacca",
  last: ""
}

const rey = {
  first: "Rey",
  lastName: undefined
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Lets assume that we had a function, &lt;code&gt;displayName&lt;/code&gt; that was responsible for obtaining the character's full name for display.&lt;/p&gt;

&lt;p&gt;We may be tempted to reach for a logical OR operator like follows.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function displayName(character) {
  const lastName = character.last || "Not specified"

  log(character.first, lastName)
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This would work well for &lt;code&gt;hanSolo&lt;/code&gt; and &lt;code&gt;rey&lt;/code&gt; but would fall short for Chewbacca, since we're specifying that his last name is "" (meaning he has no last name for our simple example). The &lt;code&gt;""&lt;/code&gt; is evaluated as falsy, so the logical OR operator would evaluate to "Not specified" in this case. This fails to meet our requirements because a lastname of "" should not cause the &lt;code&gt;displayName&lt;/code&gt; function to append "Not specified"&lt;/p&gt;

&lt;p&gt;Without the null coalescing operator, we'd generally have to check for lastName being null or undefined since an empty string is evaluated as falsy.&lt;/p&gt;

&lt;p&gt;If we change our function to the following, everything works as expected, however, it's a bit more code.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function displayName(character) {
 const lastName = character.last === null || character.last === undefined
  ? 'Not Specified'
  : character.last;

  log(character.first, lastName)
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Using the nullish coalescing operator is a lot more focused:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function displayName(character) {
  const lastName = character.last ?? "Not specified"

  log(character.first, lastName)
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is very similar to the function using the logical OR "||" except we're using two question marks instead "??" &lt;a href="https://codepen.io/ryanlanciaux/pen/YzPdbLv?editors=0010" rel="noopener noreferrer"&gt;View the example for this article here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Please &lt;a href="https://twitter.com/ryanlanciaux" rel="noopener noreferrer"&gt;find me on Twitter at @ryanlanciaux&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>codenewbie</category>
      <category>refactorit</category>
    </item>
    <item>
      <title>Snowpack with React: An awesome way to build web applications</title>
      <dc:creator>Ryan Lanciaux</dc:creator>
      <pubDate>Tue, 14 Jan 2020 07:15:03 +0000</pubDate>
      <link>https://dev.to/ryanlanciaux/snowpack-with-react-ch3</link>
      <guid>https://dev.to/ryanlanciaux/snowpack-with-react-ch3</guid>
      <description>&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/pUUAil_9yIw"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;In this article, we're going to build a React application using &lt;a href="https://www.snowpack.dev/" rel="noopener noreferrer"&gt;Snowpack&lt;/a&gt;. &lt;a href="https://www.snowpack.dev/" rel="noopener noreferrer"&gt;Snowpack&lt;/a&gt; is one of the technologies I'm most excited about right now. It's a little bit like bundler in that it's responsible for preparing an application's third-party dependencies for use on the web but it has enough differences to make it a compelling tool to explore. Instead of building every time you save your code, &lt;a href="https://www.snowpack.dev/" rel="noopener noreferrer"&gt;Snowpack&lt;/a&gt; can do it's work after you install a dependency. Lets take a look. (&lt;a href="https://github.com/ryanlanciaux/snowpack-demo" rel="noopener noreferrer"&gt;The demo application we'll be building in this article is available here&lt;/a&gt;)&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting started
&lt;/h2&gt;

&lt;p&gt;We're going to create a new project. Instead of starting our project with Create React App, Gatsby, Next, etc. we're simply going to create a new folder, cd into that folder, and run &lt;code&gt;npm init&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt; mkdir snowpack-demo
&amp;gt; cd snowpack-demo
&amp;gt; npm init
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once that's complete, we're going to install a couple of development dependencies. We'll start by including &lt;code&gt;snowpack&lt;/code&gt;, followed by &lt;code&gt;@babel/core&lt;/code&gt;, &lt;code&gt;@babel/cli&lt;/code&gt;, and &lt;code&gt;@babel/preset-react&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt; yarn add --dev snowpack
&amp;gt; yarn add --dev @babel/core @babel/cli @babel/preset-react
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Traditionally, we could run &lt;code&gt;snowpack&lt;/code&gt; through &lt;code&gt;npx&lt;/code&gt; but we'll be using snowpack's babel plugin a little later in this example.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Babel?
&lt;/h2&gt;

&lt;p&gt;Speaking of Babel, you might be asking yourself why we're using Babel with Snowpack. This is a totally valid question as Babel is usually not required with Snowpack.&lt;/p&gt;

&lt;p&gt;We're going to use JSX with our application. Unfortunately, the browser would have no idea how to handle JSX, so we're going to use Babel to help translate our code into something that the Browser can understand. Additionally, since we're using already using Babel, we're going to use Snowpacks's optional Babel plugin that will allow us to used named imports rather than importing by URL. What this means is traditionally, with Snowpack, we'd import React and ReactDOM like this.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&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;/web_modules/react.js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;ReactDOM&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;/web_modules/react-dom.js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With the (optional) Babel plugin, we can import our modules in a way that may be more familiar if we're used to things like Create React App, etc.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;ReactDOM&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;react-dom&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Behind the scenes, we're still using the files in the &lt;code&gt;web_modules&lt;/code&gt; directory created by Snowpack. The Babel plugin is translating the name to this path for us.&lt;/p&gt;

&lt;h2&gt;
  
  
  Include React
&lt;/h2&gt;

&lt;p&gt;With that out of the way, we're going to add React and ReactDOM to our project. Currently, React doesn't support ES Modules. Fortunately, some in the community have a version of React that we can use that does support ES Modules (as noted in &lt;a href="https://www.snowpack.dev/#react" rel="noopener noreferrer"&gt;the Snowpack docs&lt;/a&gt;).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;yarn add react@npm:@reactesm/react react-dom@npm:@reactesm/react-dom
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, if we run &lt;code&gt;yarn snowpack&lt;/code&gt; we can watch Snowpack perform some work against our included modules.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt; yarn snowpack
✔ snowpack installed: react, react-dom [0.79s]
✨  Done in 2.03s.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can take a look at our &lt;code&gt;web_modules&lt;/code&gt; directory and see that Snowpack created files for our newly included modules and an &lt;a href="https://github.com/WICG/import-maps" rel="noopener noreferrer"&gt;import map&lt;/a&gt; that we could use for browsers that support them.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt; ls web_modules
import-map.json
react.js
react-dom.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, we'll add &lt;a href="https://www.npmjs.com/package/live-server" rel="noopener noreferrer"&gt;live-server&lt;/a&gt;, the tool we'll use to serve our files locally.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;yarn add --dev live-server
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We're finally ready to start editing our code. We'll start by creating a boilerplate HTML page. This page will have an element with an id of &lt;code&gt;app&lt;/code&gt; where we'll attach our React application. Additionally, we'll include a JavaScript app that lives in &lt;code&gt;lib/app.js&lt;/code&gt;. This file doesn't exist currently but we'll take care of that shortly.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;html&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"en"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;Hello world example!&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"app"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"module"&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"/lib/app.js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We'll add a &lt;code&gt;.babelrc&lt;/code&gt; file where we'll add our Babel configuration&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="p"&gt;{&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;plugins&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;snowpack/assets/babel-plugin.js&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;presets&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@babel/preset-react&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, we'll create a very basic React application in &lt;code&gt;src/app.js&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;React&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;react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;ReactDOM&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;react-dom&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;App&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;h1&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Hello&lt;/span&gt; &lt;span class="nx"&gt;everyone&lt;/span&gt;&lt;span class="o"&gt;!&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h1&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;
&lt;span class="nx"&gt;ReactDOM&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;render&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;App&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&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="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can run this application in watch mode with the following commands.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;yarn babel src --out-dir lib --watch
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This runs babel against our &lt;code&gt;src&lt;/code&gt; directory and writes the transpiled files to a &lt;code&gt;lib&lt;/code&gt; directory (what we reference in &lt;code&gt;index.html&lt;/code&gt;)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;yarn live-server
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command runs live-server to watch our HTML / JavaScript for changes. Generally, I would write a script or use something like &lt;a href="https://www.npmjs.com/package/concurrently" rel="noopener noreferrer"&gt;concurrently&lt;/a&gt; that would run the two commands together as an &lt;code&gt;npm script.&lt;/code&gt; For the sake of example, however, I like to focus on these items individually.&lt;/p&gt;

&lt;p&gt;If we navigate to our browser and open the page (by default, localhost:8080) we should be greeted with the following:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/http%3A%2F%2Fryanlanciaux.com%2Fstatic%2F6780fd91444e22499021dae0aff334ed%2Fdf24b%2Fhello.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/http%3A%2F%2Fryanlanciaux.com%2Fstatic%2F6780fd91444e22499021dae0aff334ed%2Fdf24b%2Fhello.png" alt="Web page with a Hello heading" width="269" height="81"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Finally, we'll make some adjustments to our application to automatically run Snowpack when we include new dependencies. If we jump back to our &lt;code&gt;package.json&lt;/code&gt; file, we're going to add a &lt;code&gt;prepare&lt;/code&gt; script in the &lt;code&gt;scripts&lt;/code&gt; object:&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="p"&gt;{&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;name&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;snowpack-demo&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;scripts&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;prepare&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;npx snowpack&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;This &lt;code&gt;prepare&lt;/code&gt; script will run in a couple specific instances, most notably for us, after we install a new dependency. Now if we include &lt;a href="https://styled-components.com/" rel="noopener noreferrer"&gt;styled-components&lt;/a&gt;, we should see Snowpack running for us without any manual intervention.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;yarn add styled-components
yarn add v1.21.1
[1/4] 🔍  Resolving packages...
[2/4] 🚚  Fetching packages...
...
success Saved 1 new dependency.
info Direct dependencies
└─ styled-components@5.0.0
info All dependencies
└─ styled-components@5.0.0
$ npx snowpack
✔ snowpack installed: react, react-dom, styled-components. [0.75s]
✨  Done in 3.73s.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice that Snowpack command that occured after yarn finished including the dependency. We can continue to &lt;a href="http://ryanlanciaux.com/blog/2020/01/09/an-introduction-to-styled-components/" rel="noopener noreferrer"&gt;Use styled components like we would outside of an application configured with Snowpack&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/ryanlanciaux/snowpack-demo" rel="noopener noreferrer"&gt;Check out the demo application from this article here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I'm very excited about the developer experience, and performance benefits that Snowpack could unlock. I'd love to hear about any of the strategies you're using to bundle your applications or of any thoughts you have on this article. Please &lt;a href="https://twitter.com/ryanlanciaux" rel="noopener noreferrer"&gt;find me on Twitter at @ryanlanciaux&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>react</category>
      <category>javascript</category>
    </item>
    <item>
      <title>An introduction to Styled-Components with React</title>
      <dc:creator>Ryan Lanciaux</dc:creator>
      <pubDate>Thu, 09 Jan 2020 07:15:03 +0000</pubDate>
      <link>https://dev.to/ryanlanciaux/an-introduction-to-styled-components-mki</link>
      <guid>https://dev.to/ryanlanciaux/an-introduction-to-styled-components-mki</guid>
      <description>&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/FjHPo1E9HK8"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;In this article, we are going to take a quick look at styled components, a styling library for use with React. While there are many ways to style React applications, styled components stands out as an excellent way style our applications as a series of components using familiar CSS syntax.&lt;/p&gt;

&lt;p&gt;We will start by adding styled-components to our application through yarn or npm.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt; yarn add styled-components
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;From our default React application, we’ll jump over to &lt;code&gt;App.js&lt;/code&gt; and import styled from &lt;code&gt;styled-components&lt;/code&gt;. We're ready to create our first styled component that we'll call Card by typing &lt;code&gt;const card = styled.div&lt;/code&gt; - noting that our &lt;code&gt;Card&lt;/code&gt; component will render as a &lt;code&gt;div&lt;/code&gt;. We'll add a template literal directly after div and provide some CSS that defines a border, shadow, and padding — as well as a couple other properties. We should end up with something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="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="s1"&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;Card&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;div&lt;/span&gt;&lt;span class="s2"&gt;`
  border: 1px solid #ededed;
  box-shadow: 0 8px 6px -6px;
  padding: 16px;
  border-radius: 5px;
  background-color: #fafafa;
  margin: 20px 0px;
`&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&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;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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Card&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Hello&lt;/span&gt;&lt;span class="o"&gt;!&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/Card&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;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/http%3A%2F%2Fryanlanciaux.com%2Fstatic%2F10a767afbf36aba1a0e21a7d6e232940%2Fb9e4f%2Fhello.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/http%3A%2F%2Fryanlanciaux.com%2Fstatic%2F10a767afbf36aba1a0e21a7d6e232940%2Fb9e4f%2Fhello.png" alt="" width="590" height="59"&gt;&lt;/a&gt;&lt;br&gt;
&lt;br&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Passing props to styled components
&lt;/h2&gt;

&lt;p&gt;Now we can reuse this card component just like any other React component but what if we wanted to specify variations to this component? Maybe we want to have a version of the card that was highlighted a bit more.&lt;/p&gt;

&lt;p&gt;Thankfully, since this is a component, we can pass props to it and interact with them in our styled definition through an interpolation. We’ll add a &lt;code&gt;shouldHighlight&lt;/code&gt; prop to our App component specifying that &lt;code&gt;shouldHighlight = true&lt;/code&gt;. After this, we'll add a string interpolation arrow function. This function will use props and will return either our default grey color or a highlight color.&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;Card&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;div&lt;/span&gt;&lt;span class="s2"&gt;`
  border: 1px solid &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;props&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;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;shouldHighlight&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#F09&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;#EDEDED&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt;;
  box-shadow: 0 8px 6px -6px;
  padding: 16px;
  border-radius: 5px;
  background-color: #fafafa;
  margin: 20px 0px;
`&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&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;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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Card&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Hello&lt;/span&gt;&lt;span class="o"&gt;!&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/Card&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;Card&lt;/span&gt; &lt;span class="nx"&gt;shouldHighlight&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Highlighted&lt;/span&gt; &lt;span class="nx"&gt;Card&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/Card&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;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/http%3A%2F%2Fryanlanciaux.com%2Fstatic%2F73ad23f9108d060e737d5ecc68cd9d0d%2Fb9e4f%2Fhightlight_card.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/http%3A%2F%2Fryanlanciaux.com%2Fstatic%2F73ad23f9108d060e737d5ecc68cd9d0d%2Fb9e4f%2Fhightlight_card.png" alt="" width="590" height="124"&gt;&lt;/a&gt;&lt;br&gt;
&lt;br&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Themes
&lt;/h2&gt;

&lt;p&gt;So far, we’ve been providing our colors, font-sizes etc, directly in our styled components. What if we had a &lt;code&gt;Text&lt;/code&gt; component where we wanted to use the same highlight color? In our trivial example it would be relatively easy to duplicate the colors in each style definition. In a larger application, however, this could become a bit unwieldy to manage. This is where a theme is extremely useful.&lt;/p&gt;

&lt;p&gt;A &lt;a href="https://www.styled-components.com/docs/advanced" rel="noopener noreferrer"&gt;theme&lt;/a&gt;, is a javascript object where we can specify properties that we can use in our styled components. We could create a theme object that contains our colors.&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;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;colors&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;highlight&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#F09&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;grey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#EDEDED&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;Once we have this theme object, we’ll place, we’ll want to utilize a &lt;code&gt;ThemeProvider&lt;/code&gt; and pass our newly created theme to this provider as the &lt;code&gt;theme&lt;/code&gt; prop.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export default function App() {
  return (
    &amp;lt;ThemeProvider theme={theme}&amp;gt;
      &amp;lt;div className="App"&amp;gt;
        &amp;lt;Card&amp;gt;Hello!&amp;lt;/Card&amp;gt;

        &amp;lt;Card shouldHighlight&amp;gt;Highlighted Card&amp;lt;/Card&amp;gt;
        &amp;lt;Text&amp;gt;Some text&amp;lt;/Text&amp;gt;
      &amp;lt;/div&amp;gt;
    &amp;lt;/ThemeProvider&amp;gt;
  );
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now any component that is rendered under this provider has access to our theme. We can update our components to utilize the theme prop:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const Card = styled.div`
  border: 1px solid
    ${props =&amp;gt;
      props.shouldHighlight
        ? props.theme.colors.highlight
        : props.theme.colors.grey};
  box-shadow: 0 8px 6px -6px;
  padding: 16px;
  border-radius: 5px;
  background-color: #fafafa;
  margin: 20px 0px;
`;

const Text = styled.span`
  color: ${props =&amp;gt; props.theme.colors.highlight};
`;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I’ve found styled components to be an excellent way to style applications built with React (for teams that are on-board with a css-in-js based mindset). You can &lt;a href="https://codesandbox.io/s/exciting-mestorf-foph3" rel="noopener noreferrer"&gt;take a look at the finished example on CodeSandbox&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I would love to know your thoughts or of any ways you’ve found useful to style your applications. &lt;a href="https://twitter.com/ryanlanciaux" rel="noopener noreferrer"&gt;Please let me know what you think on Twitter&lt;/a&gt; or the comments here. &lt;/p&gt;

</description>
      <category>webdev</category>
      <category>react</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Tailwind with React</title>
      <dc:creator>Ryan Lanciaux</dc:creator>
      <pubDate>Thu, 02 Jan 2020 13:38:41 +0000</pubDate>
      <link>https://dev.to/ryanlanciaux/tailwind-with-react-2ncl</link>
      <guid>https://dev.to/ryanlanciaux/tailwind-with-react-2ncl</guid>
      <description>&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/kl-flSYLkhc"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Tailwind is a CSS library in a similar space to things like Bootstrap or Bulma. Tailwind is different that instead of providing CSS for full components, it provides low-level utility classes. What this means is that instead of using class=“button” or “card” or something else, you’ll define your own button by composing Tailwind’s utility classes.&lt;/p&gt;

&lt;p&gt;For an example of this, we’ll look at some HTML of a card created with Bootstrap and then a card created with Tailwind.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Bootstrap - &lt;a href="https://codepen.io/ryanlanciaux/pen/dyPzXBz" rel="noopener noreferrer"&gt;See example on CodePen&lt;/a&gt;&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- from the Bootstrap documentation
     https://getbootstrap.com/docs/4.0/components/card/
--&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"card"&lt;/span&gt; &lt;span class="na"&gt;style=&lt;/span&gt;&lt;span class="s"&gt;"width: 18rem;"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt;
    &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"card-img-top"&lt;/span&gt;
    &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://www.fillmurray.com/300/300"&lt;/span&gt;
    &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;"Card image cap"&lt;/span&gt;
  &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"card-body"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;h5&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"card-title"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Card title&lt;span class="nt"&gt;&amp;lt;/h5&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;p&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"card-text"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      Some quick example text to build on the card title and make up the bulk of
      the card's content.
    &lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"#"&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"btn btn-primary"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Go somewhere&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Tailwind - &lt;a href="https://codepen.io/ryanlanciaux/pen/KKwvMOj" rel="noopener noreferrer"&gt;See example on CodePen&lt;/a&gt;&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"w-64 rounded overflow-hidden shadow-lg"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt;
    &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"w-full"&lt;/span&gt;
    &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://www.fillmurray.com/300/300"&lt;/span&gt;
    &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;"Bill Murray Placeholder"&lt;/span&gt;
  &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"px-6 py-4"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"font-bold text-xl mb-2"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Card Title&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;p&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"text-gray-700 text-base"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      Some quick example text
    &lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"px-6 py-4"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"bg-blue-800 py-2 px-2 rounded text-white"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      Go Somewhere
    &lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You may have noticed that the Tailwind card has more verbose CSS class properties. However, we can now adjust how our component looks without changing CSS directly.&lt;/p&gt;

&lt;p&gt;For example, if we wanted to give the card a background, we could apply a bg-color class to our opening div: &lt;code&gt;&amp;lt;div class="w-64 rounded overflow-hidden shadow-lg bg-indigo-300"&amp;gt;...&amp;lt;/div&amp;gt;&lt;/code&gt;. The &lt;code&gt;bg-indigo-300&lt;/code&gt; class is one example of a Tailwind Utility Class.&lt;/p&gt;

&lt;h2&gt;
  
  
  With React
&lt;/h2&gt;

&lt;p&gt;We’re going to start with a default Create React Project.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt; npx create-react-app react-tailwind-example
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, we'll add a couple dependencies&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt; yarn add tailwindcss tailwind.macro@next @emotion/core @emotion/styled
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;small&gt;If you prefer styled-components, you could include that instead of &lt;code&gt;@emotion/core @emotion/styled&lt;/code&gt;&lt;/small&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://www.npmjs.com/package/tailwindcss" rel="noopener noreferrer"&gt;Tailwind&lt;/a&gt; is the Tailwind library.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.npmjs.com/package/tailwind.macro" rel="noopener noreferrer"&gt;Tailwind.Macro&lt;/a&gt; is a Babel plugin macro for using babel-plugin-tailwind-components package without additional configuration. Please see &lt;a href="https://github.com/kentcdodds/babel-plugin-macros" rel="noopener noreferrer"&gt;kentcdodds/babel-plugin-macros&lt;/a&gt; if you're interested in learning more about Babel plugin macros.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://emotion.sh/docs/introduction" rel="noopener noreferrer"&gt;@emotion/core | @emotion/styled&lt;/a&gt; - The css-in-js library we're using in this example.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We’re ready to start writing some example code that uses these libraries. We'll replace App.js with the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React from "react";
import styled from "@emotion/styled";
import tw from "tailwind.macro";

const Button = styled.button`
  ${tw`bg-gray-300 text-yellow-900 px-8 m-8 rounded h-20 text-3xl`}
`;

export default function() {
  return &amp;lt;Button&amp;gt;Testing&amp;lt;/Button&amp;gt;;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Example output:&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/.%2Ftailwind_output.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/.%2Ftailwind_output.png" alt="" width="" height=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The styled component, Button, is using the Tailwind Macro &lt;code&gt;tw&lt;/code&gt; to apply utility classes for things like a background color, rounded corners, font-size, etc. Combining Tailwind with Emotion or Styled-Components allows us to build flexible components quickly.&lt;/p&gt;

&lt;p&gt;Using Tailwind CSS with my React applications has been extremely useful for me. I hope you find it helpful also.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>react</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Increase your productivity with Storybook's new Component Story Format</title>
      <dc:creator>Ryan Lanciaux</dc:creator>
      <pubDate>Thu, 24 Oct 2019 21:08:56 +0000</pubDate>
      <link>https://dev.to/ryanlanciaux/increase-your-productivity-with-storybook-s-new-component-story-format-531i</link>
      <guid>https://dev.to/ryanlanciaux/increase-your-productivity-with-storybook-s-new-component-story-format-531i</guid>
      <description>&lt;p&gt;Storybook is an incredible tool for building component based frontend applications. &lt;a href="https://dev.to/ryanlanciaux/the-magic-of-a-mise-en-place-mindset-for-frontend-development-3ge0"&gt;It helps you develop the parts of your application in isolation and apply some powerful plugins to ensure quality and consistency&lt;/a&gt;. With a recent release of Storybook, there is a new way that we can define our stories that can help us eliminate duplication in other areas of our codebase.&lt;/p&gt;

&lt;h2&gt;
  
  
  Component Story Format
&lt;/h2&gt;

&lt;p&gt;Traditionally, Storybook stories look like the following code block:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt;  &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;storiesOf&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;@storybook/react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Card&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;./Card&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nf"&gt;storiesOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Card&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;default&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Card&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Something&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/Card&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These work well and &lt;strong&gt;this traditional format is not going away&lt;/strong&gt;, however, there are some extra benefits we get by using the new component story format. &lt;/p&gt;

&lt;p&gt;The new component story format looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;activityFeed/ActivityFeedItem&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;standard&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ActivityFeedItem&lt;/span&gt;
    &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Bill Murray&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
    &lt;span class="nx"&gt;conferenceName&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Some Conference&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
    &lt;span class="nx"&gt;imageUrl&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://www.fillmurray.com/128/128&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You may notice that the only Storybook specific item is the default export. The default export is a JavaScript object that takes a title that can be either the title of the story or the path to the story (this example is using a path) and &lt;a href="https://storybook.js.org/docs/formats/component-story-format/" rel="noopener noreferrer"&gt;some additional options&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;The story definition is now a standard arrow function.&lt;/p&gt;

&lt;h2&gt;
  
  
  Benefits
&lt;/h2&gt;

&lt;p&gt;One of the most immediate benefits that I've found when using the Component Story Format is testing. My tests can now reuse the stories.&lt;/p&gt;

&lt;p&gt;I've traditionally had code in my tests that was very similar to the code in my stories for wiring up components (notice that the use of the ActivityFeedItem in this test is very similar to the story above):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;render&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;getByText&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;@testing-library/react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;ActivityFeed&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;./ActivityFeed&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;has Bill Murray&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;container&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;render&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;ActivityFeedItem&lt;/span&gt;
      &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Bill Murray&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
      &lt;span class="nx"&gt;conferenceName&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Some Conference&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
      &lt;span class="nx"&gt;imageUrl&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://www.fillmurray.com/128/128&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="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;getByText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;container&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Bill Murray is speaking at&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;toBeDefined&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;Using the new format, we can leverage the stories we have already created by importing them into our tests:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;render&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;getByText&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;@testing-library/react&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 component from storybook &lt;/span&gt;
&lt;span class="c1"&gt;// instead of re-wiring a new component for the test&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;standard&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;./ActivityFeed.stories&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;has Bill Murray&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;container&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;standard&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;

  &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;getByText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;container&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Bill Murray is speaking at&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;toBeDefined&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;This is especially helpful when you have a component that has multiple states. You can make a story that represents each of the various states and import these stories directly in your tests.&lt;/p&gt;

&lt;p&gt;(Very contrived code - not real world scenario BUT should help show the concept):&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="c1"&gt;// ActivityFeed.stories.js&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;activityFeed/ActivityFeedItem&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;withBillMurray&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ActivityFeedItem&lt;/span&gt;
    &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Bill Murray&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
    &lt;span class="nx"&gt;conferenceName&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Some Conference&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
    &lt;span class="nx"&gt;imageUrl&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://www.fillmurray.com/128/128&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="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;withNicolasCage&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ActivityFeedItem&lt;/span&gt;
    &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Nicolas Cage&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
    &lt;span class="nx"&gt;conferenceName&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Some Conference&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
    &lt;span class="nx"&gt;imageUrl&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://www.placecage.com/128/128&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="c1"&gt;// ActivityFeed.test.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;render&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;getByText&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;@testing-library/react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  &lt;span class="nx"&gt;withBillMurray&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;withNicolasCage&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;./ActivityFeed.stories&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;has Bill Murray&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;container&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;withBillMurray&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;

  &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;getByText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;container&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Bill Murray is speaking at&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;toBeDefined&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;has Nicolas Cage&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;container&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;withNicolasCage&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;

  &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;getByText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;container&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Nicolas Cage is speaking at&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;toBeDefined&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;This technique also works with tools such as &lt;a href="https://www.cypress.io/" rel="noopener noreferrer"&gt;Cypress&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I'd love to know your thoughts or of any other way that you're achieving better productivity in front-end development with similar strategies.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>react</category>
      <category>productivity</category>
      <category>storybookjs</category>
    </item>
    <item>
      <title>Quick tip: How to console.log in implicitly returned arrow functions</title>
      <dc:creator>Ryan Lanciaux</dc:creator>
      <pubDate>Thu, 10 Oct 2019 19:28:06 +0000</pubDate>
      <link>https://dev.to/ryanlanciaux/quick-tip-logging-in-arrow-functions-with-an-implicit-return-4le3</link>
      <guid>https://dev.to/ryanlanciaux/quick-tip-logging-in-arrow-functions-with-an-implicit-return-4le3</guid>
      <description>&lt;p&gt;Arrow functions with implicit returns are an awesome, concise way to interact with data. &lt;/p&gt;

&lt;p&gt;An example of an arrow function with implicit return&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const sum = (a, b) =&amp;gt; a + b;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Where an arrow function &lt;strong&gt;without&lt;/strong&gt; an implicit return would look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const sum = (a, b) =&amp;gt; { return a + b; }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Very similar but in the first example, the return value of the function is inferred where in the latter, we're specifying the return statement of the function.&lt;/p&gt;

&lt;p&gt;Logging in a standard function / arrow function is pretty straight-forward&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const sum = (a, b) =&amp;gt; {
  console.log('HERE!');
  return a + b;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But how do we accomplish this same thing in an arrow function with implicit return? Many times, developers convert the function with implicit return to a standard function but this isn't necessary. &lt;/p&gt;

&lt;h2&gt;
  
  
  A potential solution
&lt;/h2&gt;

&lt;p&gt;We can take advantage of the fact that console.log is evaluated as falsy. This means that if we ran&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;if(console.log('someStatement')) { 
  // ... 
} else {
 ...
} 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We would encounter our &lt;code&gt;else&lt;/code&gt; block every time. Using this knowledge, we can now update our arrow function with logging as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const sum = (a, b) =&amp;gt; console.log('A:', a, 'B:', b) || a + b;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>javascript</category>
      <category>productivity</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
