<?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: Bianca Aspin</title>
    <description>The latest articles on DEV Community by Bianca Aspin (@baspin94).</description>
    <link>https://dev.to/baspin94</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%2F1004201%2Fd1dab5bb-982c-4300-afca-e821bbb137b5.jpeg</url>
      <title>DEV Community: Bianca Aspin</title>
      <link>https://dev.to/baspin94</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/baspin94"/>
    <language>en</language>
    <item>
      <title>What I've Coded This Week (Week 3—WWCode '100 Days of Code' Challenge)</title>
      <dc:creator>Bianca Aspin</dc:creator>
      <pubDate>Wed, 14 Feb 2024 19:44:08 +0000</pubDate>
      <link>https://dev.to/baspin94/what-ive-coded-this-week-week-3-wwcode-100-days-of-code-challenge-1him</link>
      <guid>https://dev.to/baspin94/what-ive-coded-this-week-week-3-wwcode-100-days-of-code-challenge-1him</guid>
      <description>&lt;p&gt;&lt;em&gt;Cover Image: Confused emoji wondering why the calendar arrows show up on the mobile view (left) of my React Native app but are missing on the web view (right).&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This week ended up being pretty frontend heavy, so while I didn't get anything done in Python land, I did spend a lot of time with JavaScript and CSS, with some more React Native troubleshooting (a recurring theme so far in these posts) thrown in.&lt;/p&gt;

&lt;h2&gt;
  
  
  Quick Links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;React Native—The Case of the Missing Arrows in 'React Native Calendars'&lt;/li&gt;
&lt;li&gt;JavaScript—JavaScript30 Project #3: CSS Variables&lt;/li&gt;
&lt;li&gt;JavaScript—JavaScript30 Project #4: Array Cardio (Day 1)&lt;/li&gt;
&lt;li&gt;Responsive Design—Kevin Powell's 'Conquering Responsive Layouts' (Week 1)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  React Native—The Case of the Missing Arrows in React Native Calendars
&lt;/h2&gt;

&lt;p&gt;In &lt;a href="https://dev.to/baspin94/what-ive-coded-this-week-week-2-wwcode-100-days-of-code-challenge-657#react-nativepatching-packages"&gt;my last update&lt;/a&gt;, I mentioned that I would be working with the &lt;a href="https://wix.github.io/react-native-calendars/"&gt;'React Native Calendars' library&lt;/a&gt; to build out a calendar tracker for the 'random acts of kindness' app my friend and I are working on. Little did I know that, without even doing anything to modify the default &lt;code&gt;&amp;lt;Calendar&amp;gt;&lt;/code&gt; component, I would already have debugging to do. The forward and back arrows to change months were displayed on the mobile view but not the web view.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnkb8i92aszkwp4jm9oee.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnkb8i92aszkwp4jm9oee.png" alt="Comparison of mobile view (with calendar arrows rendered) and web view (without calendar arrows rendered)" width="800" height="464"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I found a &lt;a href="https://github.com/wix/react-native-calendars/issues/801"&gt;stale GitHub issue about the missing arrows&lt;/a&gt; and saw that another user had success unearthing the arrows by modifying the arrow's &lt;code&gt;height&lt;/code&gt; and &lt;code&gt;width&lt;/code&gt; within the component's &lt;code&gt;theme&lt;/code&gt; (the working theory being that, because there was no &lt;code&gt;height&lt;/code&gt; or &lt;code&gt;width&lt;/code&gt; explicitly set for the images, they weren't rendering), so I tried this for myself:&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;View&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react-native&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;Calendar&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react-native-calendars&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;CalendarView&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;View&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;Calendar&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;arrowHeight&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="na"&gt;arrowWidth&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;50&lt;/span&gt;
                &lt;span class="p"&gt;}}&lt;/span&gt;
            &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/View&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;The result looked oddly blurry.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpgug3m81i8zy4bftnhq4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpgug3m81i8zy4bftnhq4.png" alt="Calendar with blurry arrow buttons" width="353" height="424"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Upon inspecting the page to figure out why that might be, I found out that the arrow icons are PNG files. This is what the original image looks like (you may want to get out your magnifying glass!):&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftap2zc7us4i5aua2t4lu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftap2zc7us4i5aua2t4lu.png" alt="Small right arrow which is the default arrow image used in React Native Calendars" width="24" height="24"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To get around this, I took the &lt;a href="https://github.com/wix/react-native-calendars/issues/801#issuecomment-509557261"&gt;suggestion of another user in the issue thread&lt;/a&gt; to create custom &lt;code&gt;&amp;lt;Arrow&amp;gt;&lt;/code&gt; components, utilizing SVG icons from the &lt;a href="https://www.npmjs.com/package/react-native-vector-icons"&gt;React Native Vector Icons library&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;View&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react-native&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;Calendar&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react-native-calendars&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;Icon&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-native-vector-icons/MaterialIcons&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;CalendarView&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;leftArrow&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Icon&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;keyboard-arrow-left&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
        &lt;span class="nx"&gt;size&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="nx"&gt;color&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#62BEC1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
    &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;rightArrow&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Icon&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;keyboard-arrow-right&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
        &lt;span class="nx"&gt;size&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="nx"&gt;color&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#62BEC1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
    &lt;span class="o"&gt;/&amp;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;View&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;Calendar&lt;/span&gt; 
                &lt;span class="nx"&gt;renderArrow&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{(&lt;/span&gt;&lt;span class="nx"&gt;direction&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;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;direction&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;left&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;leftArrow&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                                &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;direction&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;right&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;rightArrow&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  
                            &lt;span class="p"&gt;}}&lt;/span&gt;
            &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/View&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;Unlike PNG files, SVG files can be resized without losing resolution, which we need here. (Check out this &lt;a href="https://www.adobe.com/creativecloud/file-types/image/comparison/png-vs-svg.html#:~:text=While%20PNGs%20are%20capable%20of,size%20without%20losing%20their%20resolution."&gt;helpful comparison of PNG vs. SVG from Adobe&lt;/a&gt; for more info.)&lt;/p&gt;

&lt;p&gt;Here's what the calendar looks like now:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdfo4noytxl6e4xm8xi1i.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdfo4noytxl6e4xm8xi1i.png" alt="Web view of calendar with arrow vector icons rendered" width="294" height="366"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That's more like it! Next up with this project, I'll be doing more styling and customizations and working out some logic to keep track of the days users complete an act of kindness.&lt;/p&gt;

&lt;h2&gt;
  
  
  JavaScript—JavaScript30 Project #3: CSS Variables
&lt;/h2&gt;

&lt;p&gt;The third project in &lt;a href="https://javascript30.com/"&gt;Wes Bos's JavaScript30 course&lt;/a&gt; was an intriguing exercise that introduced me to a concept I was as yet unfamiliar with: &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/Using_CSS_custom_properties"&gt;CSS variables&lt;/a&gt;, also known as custom properties. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--vnQv5pXo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://res.cloudinary.com/dgoxoljsj/image/upload/v1707869783/CleanShot_2024-02-13_at_16.10.00_ipvetc.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--vnQv5pXo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://res.cloudinary.com/dgoxoljsj/image/upload/v1707869783/CleanShot_2024-02-13_at_16.10.00_ipvetc.gif" alt="CSS Variables Project GIF, showcasing sliders which dynamically update the spacing and blur of the image, as well as a color picker to update the color of the border and text" width="800" height="389"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;These handy variables allow you to update multiple properties simultaneously with JavaScript. Unlike the variables in the &lt;a href="https://sass-lang.com/"&gt;Sass library&lt;/a&gt; that Wes briefly mentioned in the lesson intro, which are defined when a page is compiled, regular CSS variables can dynamically update as a user interacts with the page.&lt;/p&gt;

&lt;p&gt;Before learning about CSS variables, here is how I would have written the CSS to match the color of some text with the background behind an image on the same page.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.hl&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#ffc600&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nt"&gt;img&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#ffc600&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;Then, if I wanted to change that CSS based on the value chosen from the color input selector on the page, I would need to update both the text and the background separately with JS. I'd need to select each element that needs to be updated, as well as the input, from the DOM, and attach an event listener to the input to watch for changes to the color selection and trigger a handler function. The handler would update the text color and background separately.&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;text&lt;/span&gt; &lt;span class="o"&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;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.hl&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;image&lt;/span&gt; &lt;span class="o"&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;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;img&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;input&lt;/span&gt; &lt;span class="o"&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="s1"&gt;base&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;input&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="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;handleColor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;handleColor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&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="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;color&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;
    &lt;span class="nx"&gt;image&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;background&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;While this isn't so bad with just two elements being updated, it grows in repetitiveness as more elements need to be changed at once.&lt;/p&gt;

&lt;p&gt;With CSS variables, we can pull that common value out by defining a variable for it in the root of the document (set to the default value) and then pointing to that variable next to each of the elements sharing it using &lt;code&gt;var(--variable)&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;  &lt;span class="nd"&gt;:root&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="py"&gt;--color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#ffc600&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nc"&gt;.hl&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--color&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nt"&gt;img&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;10px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--color&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, instead of using JavaScript to change the value for each element individually, we just need it to update the root value. Then, elements referencing that value will also be updated.&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;input&lt;/span&gt; &lt;span class="o"&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="s1"&gt;base&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;input&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="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;handleColor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;handleColor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&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="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setProperty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;--color&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Simplifying this code makes it much easier to create one master event handler for updating numerous elements on the page based on various user interactions, as I eventually did for this exercise. The &lt;code&gt;id&lt;/code&gt; in this case refers to the input element ('spacing', 'blur', and 'base'), which, if named similarly to the variables, makes selecting the correct value to update simple with string interpolation.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;handleChange&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;
    &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;base&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="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setProperty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`--&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setProperty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`--&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;px`&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;You can check out the &lt;a href="https://github.com/baspin94/JavaScript30/tree/master/03%20-%20CSS%20Variables"&gt;code and finished product for Project #3 on GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  A Note on the 'Input' Event
&lt;/h3&gt;

&lt;p&gt;I used the &lt;code&gt;input&lt;/code&gt; event when setting my event listeners. I was initially confused by Wes's approach of adding separate event listeners for &lt;code&gt;mousemove&lt;/code&gt; and &lt;code&gt;change&lt;/code&gt; events on the page inputs. Looking closely at the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Element/input_event"&gt;MDN reference for "input"&lt;/a&gt;, though, I realized that the &lt;code&gt;input&lt;/code&gt; event type is a new addition as of March 2023. Because it's new, someone using an older device or browser version may have issues getting the page to work as intended.&lt;/p&gt;

&lt;h2&gt;
  
  
  JavaScript—JavaScript30 Project #4: Array Cardio (Day 1)
&lt;/h2&gt;

&lt;p&gt;This project was, as promised by the title, a great workout and refresher on the various array methods, including &lt;code&gt;.filter()&lt;/code&gt;, &lt;code&gt;.map()&lt;/code&gt;, &lt;code&gt;.sort()&lt;/code&gt;, and &lt;code&gt;.reduce()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;These exercises were an excellent opportunity for me to go back and review what gets returned by each of these methods.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;.filter()&lt;/code&gt;: returns a shallow copy of the original array containing the filtered values.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;.map()&lt;/code&gt;: returns a new array containing the 'mapped' elements of the original array.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;.sort()&lt;/code&gt;: returns the &lt;strong&gt;same&lt;/strong&gt; array, sorted in place.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;.reduce()&lt;/code&gt;: returns the accumulated/aggregated value resulting from iterating through the array (the format of which will vary depending on how you've configured it; one of the &lt;code&gt;reduce&lt;/code&gt; exercises here returned an integer value; the other one an object with the tallied appearances of each 'key' element in the original array).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The only one of these methods I haven't used somewhere before was &lt;code&gt;reduce()&lt;/code&gt;, and at first, I was a little intimidated. However, I could quickly see its benefits once I took the time to slow down and understand how it works.&lt;/p&gt;

&lt;p&gt;Here is how I would have written out Question 4 () before learning about &lt;code&gt;.reduce()&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="c1"&gt;// Array.prototype.reduce()&lt;/span&gt;
&lt;span class="c1"&gt;// 4. How many years did all the inventors live all together?&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;totalLifespan&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;inventorArray&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;totalLifespan&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
    &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;inventor&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;inventorArray&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;totalLifespan&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;inventor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;passed&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;inventor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;year&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;totalLifespan&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;totalYears&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;totalLifespan&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;inventors&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Question 4:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;totalYears&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With &lt;code&gt;.reduce()&lt;/code&gt;, I was able to streamline this code quite a bit! I created a callback function, &lt;code&gt;lifespan&lt;/code&gt;, that would return the running total plus the current inventor's lifespan, passing that down the line until we reach the end of the 'inventors' array.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;lifespan&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;total&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;inventor&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;total&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;inventor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;passed&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;inventor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;year&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;totalYears&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;inventors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reduce&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;lifespan&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Question 4:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;totalYears&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You could even write that callback inline using an arrow function.&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;totalYears&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;inventors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reduce&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;total&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;inventor&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="nx"&gt;total&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;inventor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;passed&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;inventor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;year&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Question 4:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;totalYears&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can check out the &lt;a href="https://github.com/baspin94/JavaScript30/tree/master/04%20-%20Array%20Cardio%20Day%201"&gt;code and finished product for Project #4 on GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Responsive Design—Kevin Powell's 'Conquering Responsive Layouts' (Week 1)
&lt;/h2&gt;

&lt;p&gt;This past week, I started working through &lt;a href="https://courses.kevinpowell.co/conquering-responsive-layouts"&gt;Kevin Powell's 'Conquering Responsive Layouts' course&lt;/a&gt;. I'm coming in with some basic familiarity with what it means for a website to be responsive. For instance, I know that adaptable formatting and predictable behavior between devices are vital for accessibility. &lt;a href="https://www.youtube.com/@KevinPowell"&gt;Kevin's YouTube channel&lt;/a&gt; has managed to get me out of multiple CSS jams before, so I figured that this (totally free!) course would be enlightening. One week in, I've already learned a lot.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Du0l0MgG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://res.cloudinary.com/dgoxoljsj/image/upload/v1707876452/CleanShot_2024-02-13_at_18.06.26_wureai.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Du0l0MgG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://res.cloudinary.com/dgoxoljsj/image/upload/v1707876452/CleanShot_2024-02-13_at_18.06.26_wureai.gif" alt="GIF demonstrating a responsive header created as part of Week 1 project. The heading text reads &amp;quot;Responsive Layouts Don't Need to Be A Struggle&amp;quot;. Underneath some placeholder text is a 'I Want to Learn' button." width="800" height="479"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This first week, we reviewed a few foundational concepts for responsive layouts. During the first lesson, Kevin reiterated a point I'd seen him make in another video (&lt;a href="https://lnkd.in/gTUxE4gA"&gt;'5 simple tips to making responsive layouts the easy way'&lt;/a&gt;) that I watched last year while taking some initial steps to make my &lt;a href="https://parks.baspin.dev/"&gt;'Accessible Parks' app&lt;/a&gt; more responsive: HTML &lt;em&gt;is&lt;/em&gt;, by default, responsive. The decisions we make with CSS rules we add on top of that HTML are what make it unresponsive. There are two big offenders here in particular: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Fixed widths:&lt;/strong&gt; Setting the &lt;code&gt;width&lt;/code&gt; property in pixels makes it challenging to account for the wide variety of screen sizes that your layout might appear on and sets you up for having to create media queries that still won't be able to perfectly match the behavior you want. Setting &lt;code&gt;width&lt;/code&gt; with percentages instead will remove that guesswork. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;max-width&lt;/code&gt;: To account for larger screens where you don't want your layout to stretch too far, you can set the &lt;code&gt;max-width&lt;/code&gt; property using pixels. 

&lt;ul&gt;
&lt;li&gt;This is helpful because, it turns out, people have a hard time reading long, continuous lines of text stretching from one end of a big screen to the other; it makes it harder to keep track of where we are, and we don't want to have to move our heads to keep reading! This article from the Baymard Institute gives a little more background on line lengths and readability: &lt;a href="https://baymard.com/blog/line-length-readability"&gt;Readability: The Optimal Line Length&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Heights:&lt;/strong&gt; It's better to avoid assigning a &lt;code&gt;height&lt;/code&gt; property and let the &lt;code&gt;width&lt;/code&gt; and the content within the element determine the height of the container. That way, you won't run into situations where the text overflows or gets truncated. You can still add more height using &lt;code&gt;padding&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Over the next week, we'll dive into another area I've worked with before and am excited to gain better mastery of: Flexbox!&lt;/p&gt;

&lt;h2&gt;
  
  
  Looking Ahead
&lt;/h2&gt;

&lt;p&gt;That's a wrap for this week!&lt;/p&gt;

&lt;p&gt;Here's what I'll be working on until my next post:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Week 2 of &lt;a href="https://courses.kevinpowell.co/conquering-responsive-layouts"&gt;Kevin Powell's Responsive Design Course&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Working through part of Colt Steele's &lt;a href="https://www.udemy.com/course/pro-javascript/"&gt;JavaScript Pro: Mastering Advanced Concepts and Techniques&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Another project from &lt;a href="https://javascript30.com/"&gt;JavaScript30&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;More React Native Calendars (styling and customization)&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>learning</category>
      <category>coding</category>
    </item>
    <item>
      <title>What I've Coded This Week (Week 2—WWCode '100 Days of Code' Challenge)</title>
      <dc:creator>Bianca Aspin</dc:creator>
      <pubDate>Fri, 26 Jan 2024 18:59:04 +0000</pubDate>
      <link>https://dev.to/baspin94/what-ive-coded-this-week-week-2-wwcode-100-days-of-code-challenge-657</link>
      <guid>https://dev.to/baspin94/what-ive-coded-this-week-week-2-wwcode-100-days-of-code-challenge-657</guid>
      <description>&lt;p&gt;&lt;em&gt;(Cover Image: The clock I created for the second project in the 'JavaScript30' course)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;It's time for a recap of last week!&lt;/p&gt;

&lt;h2&gt;
  
  
  What I've Worked On This Week
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Quick Links
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;JavaScript—JavaScript30 Project #2: JS and CSS Clock&lt;/li&gt;
&lt;li&gt;Python—Adventures with Unit Testing&lt;/li&gt;
&lt;li&gt;React Native—Patching Packages&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  JavaScript—JavaScript30 Project #2: JS and CSS Clock
&lt;/h3&gt;

&lt;p&gt;I completed the second project in &lt;a href="https://javascript30.com/"&gt;Wes Bos's JavaScript30 course&lt;/a&gt;: a clock! This exercise was an interesting challenge that gave me more experience with CSS animations (transformations and transitions), working with dates in JavaScript, and the &lt;code&gt;setInterval&lt;/code&gt; function. &lt;/p&gt;

&lt;p&gt;I have to admit, I spent a lot of time staring at this clock, watching the minutes tick away (for debugging... but also to admire the &lt;a href="https://www.w3schools.com/cssref/func_cubic-bezier.php"&gt;cubic bezier timing function&lt;/a&gt; that mimics the movement of physical clock hands). I thought my clock looked nice and functional as is. I hadn't even considered the possibility of adding any animation to it, but seeing the pizzazz the realistic recoil of the second hand added made me want to give it a try.&lt;/p&gt;


&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
      &lt;div class="c-embed__cover"&gt;
        &lt;a href="https://www.youtube.com/shorts/JYKndP9NmG4?feature=share" class="c-link s:max-w-50 align-middle" rel="noopener noreferrer"&gt;
          &lt;img alt="" src="https://res.cloudinary.com/practicaldev/image/fetch/s--fPtYTQd2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.ytimg.com/vi/JYKndP9NmG4/hq2.jpg%3Fsqp%3D-oaymwEoCOADEOgC8quKqQMcGADwAQH4AfgCgALgA4oCDAgAEAEYFCBHKH8wDw%3D%3D%26rs%3DAOn4CLAD6F-W7OaCDsgL-LMGIKOx1u_90Q" height="360" class="m-0" width="480"&gt;
        &lt;/a&gt;
      &lt;/div&gt;
    &lt;div class="c-embed__body"&gt;
      &lt;h2 class="fs-xl lh-tight"&gt;
        &lt;a href="https://www.youtube.com/shorts/JYKndP9NmG4?feature=share" rel="noopener noreferrer" class="c-link"&gt;
          JS30 Project 2: Clock Ticking - YouTube
        &lt;/a&gt;
      &lt;/h2&gt;
        
      &lt;div class="color-secondary fs-s flex items-center"&gt;
          &lt;img alt="favicon" class="c-embed__favicon m-0 mr-2 radius-0" src="https://res.cloudinary.com/practicaldev/image/fetch/s--hN0DyTvz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://www.youtube.com/s/desktop/6148f390/img/favicon.ico" width="16" height="16"&gt;
        youtube.com
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;The tricky part was figuring out how to remedy the blip that occurred when a hand finished a complete rotation; it went back around to reset to its original position and then jumped back to where it was supposed to be.&lt;/p&gt;


&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
      &lt;div class="c-embed__cover"&gt;
        &lt;a href="https://www.youtube.com/shorts/PPATbRfz9WM?feature=share" class="c-link s:max-w-50 align-middle" rel="noopener noreferrer"&gt;
          &lt;img alt="" src="https://res.cloudinary.com/practicaldev/image/fetch/s--e4YGtV-U--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.ytimg.com/vi/PPATbRfz9WM/oar2.jpg" height="480" class="m-0" width="384"&gt;
        &lt;/a&gt;
      &lt;/div&gt;
    &lt;div class="c-embed__body"&gt;
      &lt;h2 class="fs-xl lh-tight"&gt;
        &lt;a href="https://www.youtube.com/shorts/PPATbRfz9WM?feature=share" rel="noopener noreferrer" class="c-link"&gt;
          JS30 Project 2: Visual Glitch - YouTube
        &lt;/a&gt;
      &lt;/h2&gt;
        
      &lt;div class="color-secondary fs-s flex items-center"&gt;
          &lt;img alt="favicon" class="c-embed__favicon m-0 mr-2 radius-0" src="https://res.cloudinary.com/practicaldev/image/fetch/s--hN0DyTvz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://www.youtube.com/s/desktop/6148f390/img/favicon.ico" width="16" height="16"&gt;
        youtube.com
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;In his lesson, Wes said that one way to resolve this issue would be to briefly remove the &lt;code&gt;transition&lt;/code&gt; property when the second hand reaches 12:00. However, I later found out that when I disabled &lt;code&gt;transition&lt;/code&gt;, the &lt;code&gt;transition-timing-function&lt;/code&gt; wouldn't come back automatically, so I added additional logic to my code to get that working again.&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;hands&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;hourHand&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;minuteHand&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;secondHand&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;secondDegrees&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;90&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;hand&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;hands&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nx"&gt;hand&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;transition&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;0s&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;hand&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;hands&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;hand&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;transition&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;all 0.05s&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
    &lt;span class="nx"&gt;hand&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;transitionTimingFunction&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;cubic-bezier(0.1, 2.7, 0.58, 1)&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;You can see the clock, the code, and a more detailed explanation on &lt;a href="https://github.com/baspin94/JavaScript30/tree/master/02%20-%20JS%20and%20CSS%20Clock"&gt;my GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Python—Adventures with Unit Testing
&lt;/h3&gt;

&lt;p&gt;I've been continuing to work through the daily challenges in the WWCode Python Track and using them to get more practice with writing unit tests with Pytest. I learned a valuable lesson this week.&lt;/p&gt;

&lt;p&gt;With the way I've been testing for exception handling in the challenges recently, my test would pass even before I'd written the corresponding code because a general &lt;code&gt;TypeError&lt;/code&gt; was returned when the code failed.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;odd_or_even&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;integer&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;integer&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Even&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Odd&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_error&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Given an invalid input, return a TypeError.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="n"&gt;string&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;banana&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;pytest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;raises&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;TypeError&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="nf"&gt;odd_or_even&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The test passed, but when I ran the code myself using a string as an input, this was the message I received:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;TypeError: not all arguments converted during string formatting&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This message is problematic because it doesn't provide users with a clear reason why the code failed. I wanted to clarify what needs to change with the message, "Input must be an integer."&lt;/p&gt;

&lt;p&gt;I did some research and found a very helpful resource (aside from the Pytest docs) that I will be reviewing in more detail as I continue building my unit testing skills: &lt;a href="https://pytest-with-eric.com/"&gt;Pytest with Eric&lt;/a&gt;, in particular the post, &lt;a href="https://pytest-with-eric.com/introduction/pytest-assert-exception/#Understanding-Exception-Testing"&gt;"How To Test Python Exception Handling Using Pytest Assert (A Simple Guide)"&lt;/a&gt;, which provided several examples of how to check for specific exceptions and messages.&lt;/p&gt;

&lt;p&gt;From reviewing Eric's tutorial, I determined that in addition to the code I wrote above, I would need to capture the exception output in an object, &lt;code&gt;excinfo&lt;/code&gt; (you could alias this object as anything you want, but this is how it is done in the official Pytest docs, too). That object has an attribute, value, which contains the error message. We'll convert that to a string to check against our desired message.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_error&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Given an invalid input, return a specific TypeError.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="n"&gt;string&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;banana&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;pytest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;raises&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;TypeError&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;excinfo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nf"&gt;odd_or_even&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="nf"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;excinfo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Input must be an integer.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now our test fails:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;AssertionError: assert 'not all argu...ng formatting' == 'Input must be an integer.'

E - Input must be an integer.

E + not all arguments converted during string formatting
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And now, we can modify the code to get that test to pass:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;odd_or_even&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;integer&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;integer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;TypeError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Input must be an integer.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;integer&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Even&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Odd&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  React Native—Patching Packages
&lt;/h3&gt;

&lt;p&gt;Following up from &lt;a href="https://dev.to/baspin94/what-ive-coded-this-week-week-1-wwcode-100-days-of-code-challenge-32de#react-nativerandom-acts-of-kindness-app"&gt;last week's post&lt;/a&gt;, where my friend and I were grappling with an issue with 'React Native Reanimated', the same errors came back to haunt us again this week. I forgot that, in addition to updating the plugins in the &lt;code&gt;Babel.config.js&lt;/code&gt; file (which I discussed last week), there was also a change that we'd made within the 'React Native Reanimated' node package during the troubleshooting process that also contributed to resolving that issue (thanks to this &lt;a href="https://github.com/software-mansion/react-native-reanimated/issues/4524#issuecomment-1843947671"&gt;GitHub issue&lt;/a&gt;). &lt;/p&gt;

&lt;p&gt;But that could never be more than a temporary fix because:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Whenever we next added more packages and ran &lt;code&gt;npm install&lt;/code&gt;, that tweak would get overwritten.&lt;/li&gt;
&lt;li&gt;Because the &lt;code&gt;node_modules&lt;/code&gt; directory is ignored by version control, anyone else installing the packages and running the code on their machine would encounter the same issue.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That's when &lt;a href="https://github.com/software-mansion/react-native-reanimated/issues/3614#issuecomment-1660852119"&gt;another GitHub issue&lt;/a&gt; led me to the solution: the &lt;a href="https://www.npmjs.com/package/patch-package"&gt;&lt;code&gt;patch-package&lt;/code&gt; library&lt;/a&gt;. Here's how I used &lt;code&gt;patch-package&lt;/code&gt; to fix this issue.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;I followed the &lt;a href="https://www.npmjs.com/package/patch-package"&gt;instructions to install the library&lt;/a&gt; and updated "scripts" in &lt;code&gt;package.json&lt;/code&gt; to run &lt;code&gt;patch-package&lt;/code&gt; after each install.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"scripts"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"postinstall"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"patch-package"&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;I went into &lt;code&gt;node_modules/react-native-reanimated/lib/module/index.web.js&lt;/code&gt; and updated the export default from &lt;code&gt;export { _default as default };&lt;/code&gt; to &lt;code&gt;export default _default;&lt;/code&gt; as the GitHub issue conversation suggested.&lt;/li&gt;
&lt;li&gt;I ran &lt;code&gt;npx patch-package react-native-reanimated&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;This generated a new directory, &lt;code&gt;patches&lt;/code&gt;, with a patch file containing the diff for the package, that gets accessed with each &lt;code&gt;npm install&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvpjl18vu6rrousiiyi6p.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvpjl18vu6rrousiiyi6p.png" alt="'Patches' directory created in repository containing the 'React-Reanimated' patch file" width="336" height="112"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;With this issue now put back to bed, I'm looking forward to doing a deep dive into &lt;a href="https://wix.github.io/react-native-calendars/"&gt;React Native Calendars&lt;/a&gt; over this next week.&lt;/p&gt;

&lt;h2&gt;
  
  
  Looking Ahead
&lt;/h2&gt;

&lt;p&gt;That's a wrap for this week! &lt;/p&gt;

&lt;p&gt;Here's what's in the works ahead of next week:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Continuing to explore React Native Calendars&lt;/li&gt;
&lt;li&gt;Continuing JavaScript30 and Python Daily Challenges&lt;/li&gt;
&lt;li&gt;Starting &lt;a href="https://courses.kevinpowell.co/conquering-responsive-layouts"&gt;Kevin Powell's Responsive Design Course&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I'll check in again next week to let you know how it all goes—stay tuned!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>learning</category>
      <category>coding</category>
    </item>
    <item>
      <title>What I've Coded This Week (Week 1—WWCode '100 Days of Code' Challenge)</title>
      <dc:creator>Bianca Aspin</dc:creator>
      <pubDate>Tue, 16 Jan 2024 03:22:37 +0000</pubDate>
      <link>https://dev.to/baspin94/what-ive-coded-this-week-week-1-wwcode-100-days-of-code-challenge-32de</link>
      <guid>https://dev.to/baspin94/what-ive-coded-this-week-week-1-wwcode-100-days-of-code-challenge-32de</guid>
      <description>&lt;p&gt;&lt;em&gt;(Cover Image: The 'drum kit' I created for the first project in the 'JavaScript30' course)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I'm thrilled to participate in &lt;a href="https://events.ringcentral.com/events/wwcode-days-of-code/registration"&gt;Women Who Code's '100 Days of Code Challenge'&lt;/a&gt;. I've wanted to get more involved with &lt;a href="https://www.womenwhocode.com/"&gt;Women Who Code&lt;/a&gt; for a while now (I've attended a few workshops in the past, which have all been wonderful), and so far, this challenge has been a great way to connect with a fantastic community while getting some much-needed practice with a) consistently coding every day and b) talking about what I'm working on (which I'll put into practice here now!).&lt;/p&gt;

&lt;p&gt;I picked up much of what I've learned so far about programming over 15 weeks in Flatiron School's Full-Stack Software Engineering bootcamp (which I started a year ago, a fact that boggles my mind). I learned a lot very quickly, but because of the fast pace of the program, there wasn't much time for me to reflect and go deeper to make sure I &lt;em&gt;really&lt;/em&gt; understood the fundamentals. Remedying that will be my main area of focus over the next 100 days.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I've Worked On This Week
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Quick Links
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;JavaScript—JavaScript30 Project #1: Drum Kit&lt;/li&gt;
&lt;li&gt;Python—GMail Web Scraping Tool&lt;/li&gt;
&lt;li&gt;Python—'Days of Code' Challenge&lt;/li&gt;
&lt;li&gt;Linux Command Line—OverTheWire's 'Bandit'&lt;/li&gt;
&lt;li&gt;React Native—Random Acts of Kindness App&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  JavaScript—JavaScript30 Project #1: Drum Kit
&lt;/h3&gt;

&lt;p&gt;The WWCode Front End track is working through &lt;a href="https://javascript30.com/"&gt;Wes Bos's free 'JavaScript30' course&lt;/a&gt;, which aims to strengthen programmers' vanilla JavaScript skills through 30 projects. I spent time last week tackling the first project in the course, a JavaScript drum kit! &lt;/p&gt;

&lt;p&gt;This was an entertaining exercise that got me reacquainted with event listeners and query selectors in JavaScript and introduced me to working with embedded audio. I've provided a detailed explanation of the approach I took to solve this exercise alongside my code on &lt;a href="https://github.com/baspin94/JavaScript30/tree/master/01%20-%20JavaScript%20Drum%20Kit"&gt;GitHub&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;As a bonus exercise, I also added functionality for playing the sounds and animations when the on-screen buttons are clicked (as opposed to pressed on the keyboard). The biggest challenge with the click event was figuring out how to grab the parent &lt;code&gt;.key&lt;/code&gt; &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt; even when one of its children (&lt;code&gt;&amp;lt;kbd&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;span&amp;gt;&lt;/code&gt;) got clicked. I added some logic to check whether &lt;code&gt;event.target&lt;/code&gt; was one of the child nodes and grab the &lt;code&gt;parentElement&lt;/code&gt; value instead.&lt;/p&gt;

&lt;p&gt;I'll be coming back to this project because another feature I'd like to add some time in the future is a built-in metronome (every musician's friend)!&lt;/p&gt;

&lt;h3&gt;
  
  
  Python
&lt;/h3&gt;

&lt;h4&gt;
  
  
  GMail Web Scraping Tool
&lt;/h4&gt;

&lt;p&gt;I've been on the post-bootcamp job search for several months now. One thing that would make my life ever-so-slightly easier is if there was a way to compile all the job leads I get emailed from LinkedIn and Indeed together in one place that is &lt;em&gt;not&lt;/em&gt; my email (competing for attention among all the spammy promotional emails that crowd into my inbox all day, every day).&lt;/p&gt;

&lt;p&gt;I figured I could:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;set up filters to forward job alert emails into one folder&lt;/li&gt;
&lt;li&gt;write an automation that extracts relevant information (i.e., job title, location, link to posting) from the body of each email&lt;/li&gt;
&lt;li&gt;deposit those results into a lovely, distraction-free spreadsheet (I &amp;lt;3 spreadsheets)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Perhaps there are services already established that could do something like this in my GMail inbox (for a fee), but I've wanted to get some experience with web scraping, automation, and Google's APIs, so I figured, "Why not build something myself for fun?" (It's &lt;em&gt;definitely&lt;/em&gt; not a way to procrastinate on sending out more job applications.)&lt;/p&gt;

&lt;p&gt;I'll probably expand more on this project in a future blog post, but so far, here are some new things I've learned:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Google has documentation and 'getting started' resources for the &lt;a href="https://developers.google.com/gmail/api/guides"&gt;GMail API&lt;/a&gt;, but the sample script implemented in their &lt;a href="https://developers.google.com/gmail/api/quickstart/python"&gt;'Python Quickstart'&lt;/a&gt; guide is using syntax that is documented separately in the &lt;a href="https://github.com/googleapis/google-api-python-client/blob/main/docs/start.md"&gt;Google API Python Client docs&lt;/a&gt; and &lt;a href="https://googleapis.github.io/google-api-python-client/docs/dyn/gmail_v1.html"&gt;GMail API docs&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Email messages are stored as binary data (&lt;a href="https://en.wikipedia.org/wiki/Base64"&gt;base64&lt;/a&gt;) and need to be decoded into a human-readable format (&lt;a href="https://en.wikipedia.org/wiki/ASCII"&gt;ASCII&lt;/a&gt;) before we can parse them with web-scraping libraries like &lt;code&gt;BeautifulSoup&lt;/code&gt;. Python has a built-in &lt;a href="https://docs.python.org/3/library/base64.html"&gt;base64 library&lt;/a&gt; for this purpose.&lt;/li&gt;
&lt;li&gt;Messages have multiple parts arranged in a tree (similar to the DOM in the browser), and these parts have different formats (one branch is for plain text; another is for HTML; there are others associated with various attachment types). I need to do more reading into &lt;a href="https://en.wikipedia.org/wiki/MIME"&gt;Multipurpose Internet Mail Extensions (MIME)&lt;/a&gt; for a better understanding of how this works.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Other than that, I've done a lot of debugging with &lt;code&gt;ipdb&lt;/code&gt; to zero in on key HTML structures in each email that I could incorporate into a scraping script.&lt;/p&gt;

&lt;h4&gt;
  
  
  'Days of Code' Python Challenge
&lt;/h4&gt;

&lt;p&gt;I've also been participating in the WWCode Python track's ongoing Python 'Days of Code' challenge, with a new prompt posted daily. I've been posting code and commentary on the approach I took and what I learned along the way in this GitHub repository: &lt;a href="https://github.com/baspin94/WWCode-Python-DaysOfCode-2024"&gt;WWCode-Python-DaysOfCode-2024&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Beyond solving the challenges at a basic level and then adapting my code to various use cases and edge cases, I've also been using this challenge as an opportunity to get some practice with writing unit tests (using &lt;a href="https://docs.pytest.org/en/7.1.x/contents.html"&gt;Pytest&lt;/a&gt;), applying concepts I learned in the &lt;a href="https://www.coursera.org/learn/test-and-behavior-driven-development-tdd-bdd/"&gt;Introduction to Test and Behavior Driven Development&lt;/a&gt; course I took last year.&lt;/p&gt;

&lt;p&gt;Something that has struck me throughout this first week of challenges is how a seemingly straightforward task can quickly become more complex once you start thinking about other ways people might use the program or the errors that could arise.&lt;/p&gt;

&lt;p&gt;For example, the day four prompt, &lt;code&gt;Write a program to find the sum of all elements in a list&lt;/code&gt;, was relatively straightforward to implement, assuming a smaller list comprised only of integers, but once floats (decimals) were added to the mix, things became much more complicated because the anticipated result (&lt;code&gt;0.6&lt;/code&gt;) was not what Python returned (&lt;code&gt;0.6000000000000001&lt;/code&gt;). This led me down a rabbit hole to figure out what was happening, which turned up this tutorial from the Python documentation, &lt;a href="https://docs.python.org/3/tutorial/floatingpoint.html"&gt;Floating Point Arithmetic: Issues and Limitations&lt;/a&gt;. This is a nuance related to how computers represent floating-point numbers. As humans, we typically calculate decimal fractions using base 10 notation, but computers calculate using base 2 (binary). If you're curious about what the difference is between the two, this &lt;a href="https://bjc.edc.org/June2017/bjc-r/cur/programming/4-internet/1-number-representation/1-binary.html?topic=nyc_bjc%2F4-internet.topic&amp;amp;course=bjc4nyc.html&amp;amp;novideo&amp;amp;noassignment#:~:text=In%20base%2010%2C%20there%20are,the%20place%20to%20its%20right."&gt;tutorial on Binary Representation&lt;/a&gt; from University of California, Berkeley provides a good primer.&lt;/p&gt;

&lt;p&gt;To cut a long story short, the nice, relatively short value we're used to seeing when calculating decimals is often being rounded, but the value stored in memory is often many decimal places longer. To resolve this, I updated the code to return a manually rounded result, adding an optional parameter to specify how many decimal places to round to (which defaults to 2).&lt;/p&gt;

&lt;h3&gt;
  
  
  Linux Command Line—OverTheWire's 'Bandit'
&lt;/h3&gt;

&lt;p&gt;I'm a Mac user, and macOS is a &lt;a href="https://www.geeksforgeeks.org/introduction-to-unix-system/"&gt;UNIX-based system&lt;/a&gt;, so working from the terminal has already given me experience with some of the most common commands (primarily &lt;a href="https://man7.org/linux/man-pages/man1/cd.1p.html"&gt;&lt;code&gt;cd&lt;/code&gt;&lt;/a&gt;, &lt;a href="https://man7.org/linux/man-pages/man1/ls.1.html"&gt;&lt;code&gt;ls&lt;/code&gt;&lt;/a&gt;, &lt;a href="https://man7.org/linux/man-pages/man1/touch.1.html"&gt;&lt;code&gt;touch&lt;/code&gt;&lt;/a&gt;, and &lt;a href="https://man7.org/linux/man-pages/man1/mkdir.1.html"&gt;&lt;code&gt;mkdir&lt;/code&gt;&lt;/a&gt;). However, now that I'm working more with Linux and Ubuntu to maintain a cloud-based server for ongoing projects, I'm realizing I've still got a lot to learn to harness the full power of the command line. &lt;/p&gt;

&lt;p&gt;When talking with a friend about this learning curve, he recommended I check out the "wargames" offered by the &lt;a href="https://overthewire.org/wargames/"&gt;OverTheWire&lt;/a&gt; community, starting with a game called &lt;a href="https://overthewire.org/wargames/bandit/"&gt;"Bandit"&lt;/a&gt;., which is the entry point for "absolute beginners" to get acquainted with the basic concepts needed to play other games in the collection. I'm currently on Level 7 of 34, and it's been a fun challenge so far that has me feeling like a secret agent.&lt;/p&gt;

&lt;p&gt;I don't want to give too much away because a core part of the experience is figuring out what to do with limited background information (other than a list of commands you may or may not need to solve each level). Some things I've learned so far (which may or may not have been used in the course of the game):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;a href="https://man7.org/linux/man-pages/index.html"&gt;Linux man-pages project&lt;/a&gt; is an &lt;em&gt;incredible&lt;/em&gt; resource.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://man7.org/linux/man-pages/man1/cat.1.html"&gt;&lt;code&gt;cat&lt;/code&gt;&lt;/a&gt; is not a command to summon a feline friend (drat!), but it can print file contents in your terminal (among many other things; see &lt;a href="https://www.geeksforgeeks.org/cat-command-in-linux-with-examples/"&gt;Geeks4Geeks' cat Command article&lt;/a&gt; for examples).&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://man7.org/linux/man-pages/man1/find.1.html"&gt;&lt;code&gt;find&lt;/code&gt;&lt;/a&gt; is a potent tool for searching for files in a directory, with a wide variety of criteria you can specify to narrow your search (see &lt;a href="https://www.geeksforgeeks.org/find-command-in-linux-with-examples/"&gt;Geeks4Geeks' Find Command article&lt;/a&gt; for examples).&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  React Native—'Random Acts of Kindness' App
&lt;/h3&gt;

&lt;p&gt;In addition to the above activities, which have helped me strengthen fundamentals I picked up during my coding bootcamp, I've also been collaborating with a friend to build a 'random acts of kindness' app to practice a new framework for both of us, React Native. Having focused primarily on web development over the last year, this first foray into mobile programming has definitely been a learning experience. However, the nice thing about having a React background already is that a lot of the concepts and syntax we've encountered so far with React Native are very similar.&lt;/p&gt;

&lt;p&gt;This week, we spent some time troubleshooting why we were getting errors when using React Navigation "drawers" (which allow you to have a navigation menu that opens from the side of your screen, like a drawer). The message is similar to the one below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ERROR in ./node_modules/@react-navigation/drawer/lib/module/views/legacy/Drawer.js 84:25-39

export 'default'.'Value' (imported as 'Animated') was not found in 'react-native-reanimated' (possible exports: FlatList, Image, ScrollView, Text, View, addWhitelistedNativeProps, addWhitelistedUIProps, createAnimatedComponent
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Upon further investigation, we found out from a closer review of the React Navigation  &lt;a href="https://reactnavigation.org/docs/drawer-navigator/#installation"&gt;Drawer Navigator&lt;/a&gt; docs that, in order to use the latest version of the 'React Native Reanimated' dependency, it needs to be configured a certain way, as described in its &lt;a href="https://docs.swmansion.com/react-native-reanimated/docs/fundamentals/getting-started/"&gt;installation guide&lt;/a&gt;. In the end, all we needed to do in addition to installing the requisite packages was add the React Native Reanimated plugin to our Babel configuration file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
&lt;span class="na"&gt;presets&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;  
&lt;span class="p"&gt;],&lt;/span&gt;  
&lt;span class="na"&gt;plugins&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="s1"&gt;react-native-reanimated/plugin&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;h2&gt;
  
  
  Looking Ahead
&lt;/h2&gt;

&lt;p&gt;That's a wrap for this week. For the upcoming week, I'm planning to work more with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Continuing the JavaScript30 course&lt;/li&gt;
&lt;li&gt;Building out my 'Job Alert Scraper' tool&lt;/li&gt;
&lt;li&gt;Continuing to solve the daily Python code challenges&lt;/li&gt;
&lt;li&gt;Finishing up the OverTheWire 'Bandit' game&lt;/li&gt;
&lt;li&gt;Experimenting with React Native calendar views&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I'll check in again next week to let you know how it all goes—stay tuned!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>learning</category>
      <category>coding</category>
    </item>
    <item>
      <title>Code-Along: Implementing 'Search By Criteria' Functionality with React, Formik, and Flask-SQLAlchemy</title>
      <dc:creator>Bianca Aspin</dc:creator>
      <pubDate>Wed, 12 Apr 2023 20:44:29 +0000</pubDate>
      <link>https://dev.to/baspin94/code-along-implementing-search-by-criteria-functionality-with-react-formik-and-flask-sqlalchemy-3gh6</link>
      <guid>https://dev.to/baspin94/code-along-implementing-search-by-criteria-functionality-with-react-formik-and-flask-sqlalchemy-3gh6</guid>
      <description>&lt;h2&gt;
  
  
  My Current Project
&lt;/h2&gt;

&lt;p&gt;As I reach the end of my journey as a bootcamp student, for my capstone project, I'm building an app that will allow users to search for national parks with particular accessibility-related amenities available. For today's blog, I wanted to walk through how I implemented a central piece of functionality for the app: the search. More specifically, the ability to search using multiple criteria.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Problem I'm Trying to Solve
&lt;/h3&gt;

&lt;p&gt;The search was at the heart of why I had the idea to create this app in the first place.  In the official &lt;a href="https://www.nps.gov/subjects/digital/nps-apps.htm" rel="noopener noreferrer"&gt;National Park Service mobile app&lt;/a&gt;, a user can search for parks to explore based on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;their proximity to the park&lt;/li&gt;
&lt;li&gt;the name of the park&lt;/li&gt;
&lt;li&gt;the state the park is located in&lt;/li&gt;
&lt;li&gt;activities available at the park&lt;/li&gt;
&lt;li&gt;topics discussed at the park&lt;/li&gt;
&lt;li&gt;the type of park (e.g., park, monument, recreation area)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fop03gowuldzbivx4dweq.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fop03gowuldzbivx4dweq.jpeg" alt="Screenshot from the official National Park Service mobile app showing the various filters available"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That's a lot of search options! However, despite there being a wide range of accessible offerings at the parks, there currently isn't an easy way for users to find parks based on the accessibility offerings available. A user has to click into each park, navigate to the amenities section, and from there, find the relevant section on accessibility.&lt;/p&gt;

&lt;p&gt;The National Park Service website provides a &lt;a href="https://www.nps.gov/subjects/accessibility/plan-your-visit.htm" rel="noopener noreferrer"&gt;map of accessibility in the national parks&lt;/a&gt;, showing the location of all parks in the United States with accessible features and services. However, clicking on each location only provides a link to the park's accessibility page. There's no way to see at a glance which amenities are available. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbfh3h269u975g74ghdka.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbfh3h269u975g74ghdka.png" alt="Screenshot of the 'Accessibility' map on the official National Parks website, showing a universal wheelchair icon at each park location with accessible features, and a tooltip directing users to the corresponding park's accessibility page"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There's no way to know whether "accessibility" at a given park means having wheelchair-accessible trails, having a sign-language interpreter for guided tours, or having tactile exhibits for those with visual impairments. The user has to manually search each page to whittle down which ones have the amenities they need to make the most of their trip, which is needlessly time-consuming. &lt;/p&gt;

&lt;h3&gt;
  
  
  My Vision for the Search Function
&lt;/h3&gt;

&lt;p&gt;When I first sketched out what I wanted the user interface to look like, I knew I wanted the homepage to be a list of the various accessibility and accessibility-adjacent (e.g., cellular signal, access to groceries, access to drinking water) amenities available at the parks. I wanted users to be able to select (by clicking the corresponding checkbox) any of the criteria that would help them decide where to go, click 'Search,' and have a list of parks returned to them matching all the criteria they selected.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz01yagsfnu13bcbrxzpp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz01yagsfnu13bcbrxzpp.png" alt="My initial sketch of the search page design, with a header at the top, three columns of checkboxes, and a search button at the bottom"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's code along together to make that vision a reality!&lt;/p&gt;

&lt;h3&gt;
  
  
  Create 'Search' and 'Results' Components
&lt;/h3&gt;

&lt;p&gt;We'll start by creating two components to house the search and results, respectively, and importing those into our main app to add them to the component tree. At the same time, let's add some basic routing by importing &lt;a href="https://v5.reactrouter.com/web/api/Switch" rel="noopener noreferrer"&gt;&lt;code&gt;Switch&lt;/code&gt;&lt;/a&gt; and &lt;a href="https://v5.reactrouter.com/web/api/Route" rel="noopener noreferrer"&gt;&lt;code&gt;Route&lt;/code&gt;&lt;/a&gt; from &lt;a href="https://v5.reactrouter.com/web/guides/quick-start" rel="noopener noreferrer"&gt;React Router&lt;/a&gt;. &lt;em&gt;(Note: I'm using version 5 of React Router here.)&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// App.js&lt;/span&gt;

&lt;span class="c1"&gt;// React Imports&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;React&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Switch&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Route&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react-router-dom&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Component Imports&lt;/span&gt;
&lt;span class="c1"&gt;// Note: This import reference will vary based on your file structure. In this case, the main App is stored outside the 'Components' folder.&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;Search&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;./Components/Search&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;Results&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;./Components/Results&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;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;Switch&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Route&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/search&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;Search&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/Route&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Route&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/results&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;Results&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/Route&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;/Switch&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

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

&lt;/div&gt;



&lt;h3&gt;
  
  
  Create the Initial Form
&lt;/h3&gt;

&lt;p&gt;Next, in the search component, let's import React's &lt;a href="https://react.dev/reference/react/useState" rel="noopener noreferrer"&gt;&lt;code&gt;useState&lt;/code&gt;&lt;/a&gt; and &lt;a href="https://react.dev/reference/react/useEffect" rel="noopener noreferrer"&gt;&lt;code&gt;useEffect&lt;/code&gt;&lt;/a&gt; hooks. We'll put those to work right away, fetching the amenity data from the server from within &lt;code&gt;useEffect&lt;/code&gt; with an empty dependency array so that the &lt;code&gt;GET&lt;/code&gt; request only gets sent when the component initially renders, not continuously. Once that data is successfully retrieved, we'll save this array of amenity objects as a state variable.&lt;/p&gt;

&lt;p&gt;With the amenities array saved in state, we can then iterate through using the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map" rel="noopener noreferrer"&gt;&lt;code&gt;map()&lt;/code&gt;&lt;/a&gt; method. Cycling through each amenity object in the array, we'll map its properties onto the attributes of an &lt;code&gt;&amp;lt;input&amp;gt;&lt;/code&gt; element. The end result of the map will be a new array of checkbox elements that can then be added within the overall &lt;code&gt;&amp;lt;form&amp;gt;&lt;/code&gt; being returned by the &lt;code&gt;Search&lt;/code&gt; component.&lt;/p&gt;

&lt;p&gt;Here's what the user interface should look like so far (without adding styling, for simplicity):&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpw7jlregs05unyywt8zi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpw7jlregs05unyywt8zi.png" alt="Screenshot of basic search page, a single column list of checkboxes for all amenities available"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here's what the code should look like so far:&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;// Search.js&lt;/span&gt;

&lt;span class="c1"&gt;// Importing React hooks&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useEffect&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Search&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="c1"&gt;// Setting state for amenities&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;amenities&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setAmenities&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;([])&lt;/span&gt;

    &lt;span class="c1"&gt;// Fetching amenities from within useEffect&lt;/span&gt;
    &lt;span class="nf"&gt;useEffect&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="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/amenities&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;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;amenityData&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setAmenities&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;amenityData&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[])&lt;/span&gt;

    &lt;span class="c1"&gt;// Iterating through amenities to create an array 'checkbox' input elements.&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;checkboxes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;amenities&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;amenity&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;div&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;amenity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;label&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;input&lt;/span&gt;
                    &lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;checkbox&lt;/span&gt;&lt;span class="dl"&gt;"&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;checked&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
                    &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;amenity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
                &lt;span class="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="nx"&gt;amenity&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;/label&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;br&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;        &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;

    &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;h1&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Search&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="c1"&gt;// Inserting that array of checkboxes into the form.&lt;/span&gt;
                &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;checkboxes&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;input&lt;/span&gt; &lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;submit&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Search&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="sr"&gt;/form&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;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;Search&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One thing that you'll notice looking at the code above is that each of the checkbox elements has the same name, "checked". This is by design, as we'll cover in the next section.&lt;/p&gt;

&lt;h3&gt;
  
  
  Configure Formik
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://formik.org/" rel="noopener noreferrer"&gt;Formik&lt;/a&gt; is an incredibly useful React library for managing state within our forms. Setting up the &lt;a href="https://formik.org/docs/api/useFormik" rel="noopener noreferrer"&gt;&lt;code&gt;useFormik&lt;/code&gt;&lt;/a&gt; hook and using its built-in state and change handlers takes out a lot of the work that comes with setting up form fields as &lt;a href="https://legacy.reactjs.org/docs/forms.html#controlled-components" rel="noopener noreferrer"&gt;controlled components&lt;/a&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="c1"&gt;// Search.js&lt;/span&gt;

&lt;span class="c1"&gt;// Other React imports&lt;/span&gt;

&lt;span class="c1"&gt;// Importing Formik&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;useFormik&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;formik&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Search&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="c1"&gt;// State-setting, useEffect fetching, etc.&lt;/span&gt;

    &lt;span class="c1"&gt;// Initializing the useFormik hook&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;formik&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useFormik&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="na"&gt;initialValues&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;checked&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="na"&gt;onSubmit&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;values&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;values&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;

    &lt;span class="c1"&gt;// checkboxes, return, etc.&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the snippet of code above, we're initializing the &lt;code&gt;useFormik&lt;/code&gt; hook. We're only specifiying one field here, 'checked' — corresponding with the &lt;code&gt;name&lt;/code&gt; attribute that we assigned to each of the checkbox elements earlier — and setting it equal to an empty array for its initial value. Per &lt;a href="https://formik.org/docs/examples/checkboxes" rel="noopener noreferrer"&gt;Formik's documentation on forms with checkbox groups&lt;/a&gt;, "given that the fields all share the same &lt;code&gt;name&lt;/code&gt;, Formik will automagically bind them to a single array". Anytime we click on a checkbox, that checkbox's value (which we've set to the amenity's unique ID) gets added to that array. If we click on the same box again to uncheck it, that value gets removed from the array.&lt;/p&gt;

&lt;p&gt;Of course, to accomplish that, let's not forget that Formik's handlers need to get added on to the form elements. The &lt;code&gt;formik.handleChange&lt;/code&gt; prop should get passed in to each input's &lt;code&gt;onChange&lt;/code&gt; attribute:&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;// Search.js&lt;/span&gt;

&lt;span class="c1"&gt;// imports&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Search&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="c1"&gt;// State-setting, useEffect fetching, Formik set-up, etc.&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;checkboxes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;amenities&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;amenity&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;div&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;amenity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;label&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;input&lt;/span&gt;
                        &lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;checkbox&lt;/span&gt;&lt;span class="dl"&gt;"&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;checked&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
                        &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;amenity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
                        &lt;span class="c1"&gt;// Adding Formik's built-in onChange handler.&lt;/span&gt;
                        &lt;span class="nx"&gt;onChange&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;formik&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;handleChange&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="nx"&gt;amenity&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;/label&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;br&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;        &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="c1"&gt;// Return, etc.&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;formik.handleSubmit&lt;/code&gt; prop should get added to the overall form's &lt;code&gt;onSubmit&lt;/code&gt; attribute:&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;// Search.js&lt;/span&gt;

&lt;span class="c1"&gt;// imports &lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Search&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// State-setting, useEffect fetching, Formik set-up, etc.&lt;/span&gt;
    &lt;span class="c1"&gt;// Checkboxes&lt;/span&gt;

    &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;h1&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Search&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;form&lt;/span&gt; &lt;span class="nx"&gt;onSubmit&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;formik&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;handleSubmit&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;checkboxes&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;input&lt;/span&gt; &lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;submit&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Search&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="sr"&gt;/form&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;Now, let's hop back to our &lt;code&gt;useFormik&lt;/code&gt; hook and take a closer look at &lt;code&gt;onSubmit&lt;/code&gt;. Formik initially receives an array of strings from the form. We're going to want to take those individual strings and join them together into one string, which we can accomplish using the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/join" rel="noopener noreferrer"&gt;&lt;code&gt;join()&lt;/code&gt;&lt;/a&gt; method.&lt;/p&gt;

&lt;p&gt;Here's what that updated code should look like now:&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;// Search.js&lt;/span&gt;

&lt;span class="c1"&gt;// imports&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Search&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="c1"&gt;// State-setting, useEffect fetching&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;formik&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useFormik&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="na"&gt;initialValues&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;checked&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="na"&gt;onSubmit&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;values&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;value_array&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;values&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;checked&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
            &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Value Array:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;value_array&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;value_string&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;value_array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
            &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Value String:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;value_string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;

    &lt;span class="c1"&gt;// Checkboxes, return, etc.&lt;/span&gt;

&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And here's what output should look like when printed in the browser console:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3sn298d5l17zl9v15gtl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3sn298d5l17zl9v15gtl.png" alt="Screenshot of Search page with top three amenities checked, with the browser developer tools open at the side, showing a printout of the checkbox values in the console"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Joining these ids together into one string will make communicating our request to the server much easier, as we'll discuss in the next part. &lt;/p&gt;

&lt;p&gt;Before I realized that I could pass this string of multiple ids as a parameter in my fetch request to my server, I tried setting up a series of fetch requests with each individual amenity ID to return arrays of matching park objects and then filtering through those arrays to find the intersecting records. I won't go into the nitty-gritty details here, but suffice it to say that, not getting the expected results 30 lines of code later, there is no straightforward way of accomplishing this kind of filtering with JavaScript. However, utilizing the powerful data manipulation capabilities of Python and SQL, this task is much simpler to accomplish on the backend!&lt;/p&gt;

&lt;h2&gt;
  
  
  Backend
&lt;/h2&gt;

&lt;p&gt;The backend of this project uses Python, Flask, and SQLAlchemy. &lt;em&gt;(Note: I won't get into the details of the initial configuration of those libraries but encourage you to check out the &lt;a href="https://flask.palletsprojects.com/en/2.2.x/" rel="noopener noreferrer"&gt;Flask&lt;/a&gt; and &lt;a href="https://flask-sqlalchemy.palletsprojects.com/en/3.0.x/" rel="noopener noreferrer"&gt;Flask-SQLAlchemy&lt;/a&gt; docs for more background.)&lt;/em&gt; &lt;/p&gt;

&lt;h3&gt;
  
  
  Create API Resource and Route
&lt;/h3&gt;

&lt;p&gt;To build out the route that we'll use to return search results, we'll start by creating a new API resource, &lt;code&gt;'ParksByAmenityIds'&lt;/code&gt;, with a &lt;code&gt;GET&lt;/code&gt; method that takes a string of ids as a parameter (hey, that sounds like what we just made on the frontend!). Before building out the logic within that resource, let's immediately go ahead and add this resource and the corresponding endpoint below (it is very easy to forget otherwise!).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# app.py
&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;flask&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;make_response&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;flask_restful&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Resource&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;api&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Amenity&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ParksByAmenityIds&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Resource&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;id_string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;pass&lt;/span&gt;

&lt;span class="n"&gt;api&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_resource&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ParksByAmenityIds&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;/park_amenities/&amp;lt;string:id_string&amp;gt;&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With that out of the way, let's build out the underlying logic. &lt;/p&gt;

&lt;h3&gt;
  
  
  Build Out Query Logic
&lt;/h3&gt;

&lt;p&gt;First, we'll split the &lt;code&gt;id_string&lt;/code&gt; into an array of separate ids.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;id_array&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;id_string&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;,&lt;/span&gt;&lt;span class="sh"&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 use a &lt;a href="https://www.w3schools.com/python/python_lists_comprehension.asp" rel="noopener noreferrer"&gt;list comprehension&lt;/a&gt; to convert those id elements from strings into integers.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;int_ids&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="nb"&gt;id&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;id_array&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, we can get a list of the parks that have any (but not all) of the specified amenities by querying the &lt;code&gt;ParkAmenity&lt;/code&gt; join table. We can use the &lt;a href="https://docs.sqlalchemy.org/en/20/core/sqlelement.html#sqlalchemy.sql.expression.ColumnOperators.in_" rel="noopener noreferrer"&gt;&lt;code&gt;.in_&lt;/code&gt; column operator&lt;/a&gt; (which operates similarly to &lt;a href="https://www.w3schools.com/python/ref_keyword_in.asp" rel="noopener noreferrer"&gt;Python's &lt;code&gt;in&lt;/code&gt; keyword&lt;/a&gt;) to return all the parks with a matching amenity id. (For the example I used with amenity ids 1, 2, and 3, there were 276 items returned with duplicates.)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;all_matching_amenities&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;amenity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to_dict&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;amenity&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;ParkAmenity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ParkAmenity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;amenity_id&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;in_&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;int_ids&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;all&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 use another list comprehension to create a new list of all the park IDs from the result of the &lt;code&gt;all_matching_amenities&lt;/code&gt; query.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;all_park_ids&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;element&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;park&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;id&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;element&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;all_matching_amenities&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Using yet another list comprehension, let's return all of the ids which appear in the park ID list as many times as there are amenities we're searching for (in this case, we've got a list of three amenities). We're using the &lt;a href="https://www.w3schools.com/python/ref_list_count.asp" rel="noopener noreferrer"&gt;&lt;code&gt;.count()&lt;/code&gt; method&lt;/a&gt; as well as finding the length of our amenities list with &lt;a href="https://www.w3schools.com/python/ref_func_len.asp" rel="noopener noreferrer"&gt;&lt;code&gt;len()&lt;/code&gt;&lt;/a&gt; to make this comparison. The result will be a list of all the park ids connected to all the specified amenities.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;multiple_matches&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="nb"&gt;id&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;all_park_ids&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;all_park_ids&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;count&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;int_ids&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 quickly remove all of the duplicates by turning that list into a set with &lt;a href="https://www.w3schools.com/python/python_sets.asp" rel="noopener noreferrer"&gt;Python's &lt;code&gt;set()&lt;/code&gt; constructor&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;unique_matches&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;multiple_matches&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, we've whittled down 276 items that match at least one criterion to a set of 18 items that match all three criteria — fantastic!&lt;/p&gt;

&lt;p&gt;Using those unique matches, we can now query the &lt;code&gt;Parks&lt;/code&gt; table (again using the &lt;code&gt;.in_&lt;/code&gt; column operator) to return all the parks with an id appearing in our new set of unique matches. This list of park objects (with all their details, not just the ids) is what our server will send back to the frontend in response to our search request.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;parks&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;park&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to_dict&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;park&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;Park&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Park&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;in_&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;unique_matches&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;()]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Add Error Handling if No Matches Found
&lt;/h3&gt;

&lt;p&gt;Before we tie this back together with our frontend, we should add some error handling. It will not be uncommon for users to select a combination of criteria that won't yield any matches. We'll want to let the frontend know if this is the case so that it can render an error message to the user accordingly. In this case, we'll add a clause that specifies that if the length of the list of parks returned is 0, the server should send back an error.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;parks&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;make_response&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;error&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;No matching parks.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="mi"&gt;404&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;

&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;make_response&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;parks&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="mi"&gt;200&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here's what the entire resource looks like, all put together:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# app.py
&lt;/span&gt;
&lt;span class="c1"&gt;# imports, additional resources/routes
&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ParksByAmenityIds&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Resource&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;id_string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;id_array&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;id_string&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;,&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;int_ids&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="nb"&gt;id&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;id_array&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

        &lt;span class="n"&gt;all_matching_amenities&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;amenity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to_dict&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;amenity&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;ParkAmenity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ParkAmenity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;amenity_id&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;in_&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;int_ids&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;()]&lt;/span&gt;
        &lt;span class="n"&gt;all_park_ids&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;element&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;park&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;id&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;element&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;all_matching_amenities&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="n"&gt;multiple_matches&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="nb"&gt;id&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;all_park_ids&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;all_park_ids&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;count&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;int_ids&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
        &lt;span class="n"&gt;unique_matches&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;multiple_matches&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="n"&gt;parks&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;park&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to_dict&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;park&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;Park&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Park&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;in_&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;unique_matches&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;()]&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;parks&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;make_response&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;error&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;No matching parks.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
                &lt;span class="mi"&gt;404&lt;/span&gt;
            &lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;

        &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;make_response&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="n"&gt;parks&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="mi"&gt;200&lt;/span&gt;
            &lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;

&lt;span class="n"&gt;api&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_resource&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ParksByAmenityIds&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;/park_amenities/&amp;lt;string:id_string&amp;gt;&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Tying the Frontend and Backend Together
&lt;/h2&gt;

&lt;p&gt;Now that we've got this route built out, let's update the Formik &lt;code&gt;onSubmit&lt;/code&gt; handler with that route to fetch the matching parks from the server. We'll add a clause for rendering an error on the search page if no matches are found. We'll set up &lt;code&gt;searchError&lt;/code&gt; as a boolean state variable and have the error message render conditionally based on whether the error state is true.&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;// Search.js&lt;/span&gt;

&lt;span class="c1"&gt;// imports&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Search&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;amenities&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setAmenities&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;([])&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;searchError&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setSearchError&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;// useEffect fetching&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;formik&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useFormik&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="na"&gt;initialValues&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;checked&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="na"&gt;onSubmit&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;values&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;value_array&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;values&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;checked&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;value_string&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;value_array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
            &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`/park_amenities/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;value_string&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&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;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&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;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ok&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                        &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
                        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;parkData&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;parkData&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
                    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                        &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
                        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setSearchError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
                    &lt;span class="p"&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;span class="c1"&gt;// Checkboxes&lt;/span&gt;

    &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;h1&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Search&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="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;searchError&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;p&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;No&lt;/span&gt; &lt;span class="nx"&gt;matches&lt;/span&gt; &lt;span class="nx"&gt;found&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/p&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;                &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;form&lt;/span&gt; &lt;span class="nx"&gt;onSubmit&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;formik&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;handleSubmit&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;checkboxes&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;input&lt;/span&gt; &lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;submit&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Search&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="sr"&gt;/form&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;To be able to render those matches in our 'Results' component, we'll need to establish &lt;code&gt;parks&lt;/code&gt; as a state variable in the parent component (&lt;code&gt;App&lt;/code&gt;) and pass those down to &lt;code&gt;Search&lt;/code&gt; and &lt;code&gt;Results&lt;/code&gt; as props.&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;// App.js&lt;/span&gt;

&lt;span class="c1"&gt;// React Imports&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;React&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Additional Imports&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="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;parks&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setParks&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;([])&lt;/span&gt;

    &lt;span class="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;Switch&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Route&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/search&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;Search&lt;/span&gt; &lt;span class="nx"&gt;setParks&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;setParks&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/Route&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Route&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/results&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;Results&lt;/span&gt; &lt;span class="nx"&gt;parks&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;parks&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/Route&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;/Switch&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Now, upon a successful search, we can use the &lt;code&gt;setParks&lt;/code&gt; prop to save those matches in state. We'll also use the &lt;a href="https://v5.reactrouter.com/web/api/Hooks/usehistory" rel="noopener noreferrer"&gt;&lt;code&gt;useHistory&lt;/code&gt;&lt;/a&gt; hook from React Router to send us to the Results page upon a successful search using the &lt;code&gt;.push()&lt;/code&gt; method.&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;// Search.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;useHistory&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react-router-dom&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;// Additional Imports&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Search&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;setParks&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// state-setting&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;history&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useHistory&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="c1"&gt;// useEffect fetching&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;formik&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useFormik&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="na"&gt;initialValues&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;checked&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="na"&gt;onSubmit&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;values&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;value_array&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;values&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;checked&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;value_string&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;value_array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
            &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`/park_amenities/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;value_string&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&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;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&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;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ok&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                        &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
                        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;parkData&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setParks&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;parkData&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
                        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&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;history&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/results&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="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                        &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
                        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setSearchError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
                    &lt;span class="p"&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;span class="c1"&gt;// checkboxes, return, etc.&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Last, let's quickly get a basic &lt;code&gt;Results&lt;/code&gt; component built out:&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;// Results.js&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Results&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;parks&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;li_parks&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;parks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;park&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;li&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;park&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;park&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;/li&lt;/span&gt;&lt;span class="err"&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;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;h1&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Results&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ul&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;li_parks&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;/ul&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;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;Results&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And there we have it, a successful search — hopefully the first of many for our users!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9fr2qkgc92r59gyc4udh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9fr2qkgc92r59gyc4udh.png" alt="Screenshot of the results page, featuring a bulleted list of all 18 parks matching the search criteria"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>react</category>
      <category>tutorial</category>
      <category>python</category>
    </item>
    <item>
      <title>An Alt-Text Primer</title>
      <dc:creator>Bianca Aspin</dc:creator>
      <pubDate>Thu, 30 Mar 2023 21:13:15 +0000</pubDate>
      <link>https://dev.to/baspin94/an-alt-text-primer-53fd</link>
      <guid>https://dev.to/baspin94/an-alt-text-primer-53fd</guid>
      <description>&lt;h2&gt;
  
  
  An Alt-Text Primer
&lt;/h2&gt;

&lt;p&gt;In my post last month about &lt;a href="https://dev.to/baspin94/an-introduction-to-screen-readers-and-html-accessibility-212c"&gt;Screen Readers and HTML Accessibility&lt;/a&gt;, I touched on some fundamental aspects of how the screen reader navigates the page and makes the web browsing experience more &lt;a href="https://webaim.org/articles/pour/perceivable" rel="noopener noreferrer"&gt;perceivable&lt;/a&gt; and &lt;a href="https://webaim.org/articles/pour/operable" rel="noopener noreferrer"&gt;operable&lt;/a&gt; for users with visual disabilities. I also mentioned that many newcomers to coding first hear about screen readers and accessibility in the context of images—specifically, the &lt;code&gt;alt&lt;/code&gt; tag used within &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt; HTML elements. As promised, I'm returning to explore that topic in more detail today.&lt;/p&gt;

&lt;h3&gt;
  
  
  What is Alt-Text?
&lt;/h3&gt;

&lt;p&gt;Alternative text, often shortened to 'alt-text,' is precisely what it sounds like—a text alternative for a non-text element, such as an image or graphic. &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/img#accessibility_concerns" rel="noopener noreferrer"&gt;Mozilla's MDN Web Docs&lt;/a&gt; describe that the HTML &lt;code&gt;alt&lt;/code&gt; attribute is a container for text describing an image. A screen reader will grab the text in this &lt;code&gt;alt&lt;/code&gt; tag and read it in place of the image. &lt;/p&gt;

&lt;p&gt;Beyond screen reader accessibility, there are other benefits of the &lt;code&gt;alt&lt;/code&gt; tag, too; it's what renders in place of an image that can't load (perhaps due to a bad internet connection or a broken link), and it also factors into the visibility of a website on search engines (&lt;a href="https://developers.google.com/search/docs/fundamentals/seo-starter-guide" rel="noopener noreferrer"&gt;Search Engine Optimization&lt;/a&gt;, aka SEO).&lt;/p&gt;

&lt;p&gt;The MDN Docs state that an &lt;code&gt;alt&lt;/code&gt; tag "isn't mandatory but is &lt;strong&gt;incredibly useful&lt;/strong&gt; for accessibility." This is &lt;em&gt;technically&lt;/em&gt; true in that omitting the &lt;code&gt;alt&lt;/code&gt; tag won't bring a page crashing down like a misplaced comma or forgotten closing tag will. But in practice, if there is one takeaway that you get from this post at all, it's that &lt;strong&gt;alt tags should &lt;em&gt;always&lt;/em&gt; be included on our images.&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  What Happens if I Don't Include Alt-Text?
&lt;/h3&gt;

&lt;p&gt;Adding &lt;code&gt;alt&lt;/code&gt; tags to images is often considered low-hanging fruit for making a website more accessible, and yet inaccessible images remain one of the most common issues. By not including alt text, we risk depriving our screen reader users of important information and added context that images provide to our sighted users.&lt;/p&gt;

&lt;p&gt;There are a couple of different things that a screen reader might do when it encounters an image without an &lt;code&gt;alt&lt;/code&gt; tag:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Read the image's &lt;code&gt;src&lt;/code&gt; tag (typically the image's URL or filename) in place of the image. If the filename is descriptive of the contents, this could be better than nothing. Often though, this is something like 'IMG_1598.jpg' or a lengthy Google Images link that reads like a jumble of random characters.&lt;/li&gt;
&lt;li&gt;Announce "image" or "graphic" and leave it at that. What is contained within the image will remain a mystery to the user—was it a graphic important to their understanding of the surrounding material or a piece of decorative clip art?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can see and hear an example of how screen readers interpret an image with vs. without an &lt;code&gt;alt&lt;/code&gt; tag in the brief example below, which demos two standard screen reader technologies (&lt;a href="https://support.apple.com/guide/voiceover/welcome/mac" rel="noopener noreferrer"&gt;VoiceOver for Mac&lt;/a&gt; and &lt;a href="https://support.google.com/chromebook/answer/7031755?hl=en" rel="noopener noreferrer"&gt;ChromeVox&lt;/a&gt;):&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/NvqasTVoW98"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;For those who want another practical perspective of how alt-text can go wrong, check out accessibility engineer Steffany Newman of &lt;a href="https://www.youtube.com/@WebAccessibility" rel="noopener noreferrer"&gt;Web Accessibility Education&lt;/a&gt;'s video showing examples of poorly executed alt-text on a popular e-commerce website you may have heard of before:&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/Dh9zDy_Yfkw"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h3&gt;
  
  
  What Should I Include in my Alt-Text?
&lt;/h3&gt;

&lt;p&gt;Shakespeare's Hamlet might have said that "To be or not to be?" is &lt;em&gt;the&lt;/em&gt; question, but that was before the internet came along and web developers, designers, and content creators were faced with the actual ultimate question: what goes inside that &lt;code&gt;alt&lt;/code&gt; attribute we've been discussing? The answer is: "it depends." However, there are a few important points to remember that can guide us.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;code&gt;alt&lt;/code&gt; tags for decorative images should be empty
&lt;/h4&gt;

&lt;p&gt;Our gut reaction to hearing that we should include &lt;code&gt;alt&lt;/code&gt; tags on all of our images might be to say, "Okay, I'm going to include alt-text on every. single. image. on my website." However, there's a difference between including an &lt;code&gt;alt&lt;/code&gt; tag on every image and including a text description inside each tag. &lt;/p&gt;

&lt;p&gt;As it turns out, not every image needs a description. If it's a purely decorative image—that is, it doesn't include any meaningful content, it's only used for layout, and deleting the image wouldn't do anything to impact the understanding of the surrounding text for our sighted users—all we need to include in the &lt;code&gt;alt&lt;/code&gt; tag is an empty string (you may also hear this referred to as a null &lt;code&gt;alt&lt;/code&gt; attribute). This tells the screen reader that it can ignore the image. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmdn80hy0xnz7ar3xpu2d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmdn80hy0xnz7ar3xpu2d.png" alt="Floral Border as an Example of a Decorative Image"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;(&lt;a href="https://thenounproject.com/icon/floral-divider-4899808/" rel="noopener noreferrer"&gt;By KEN111 via the Noun Project, CC-BY 3.0&lt;/a&gt;)&lt;/em&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;!-- Don't Do This: --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"pretty_flower_border.jpg"&lt;/span&gt; &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;"Floral Border"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="c"&gt;&amp;lt;!-- Do This: --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"pretty_flower_border.jpg"&lt;/span&gt; &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Adding a text description where it isn't needed will add (literal) noise to the screen reader's readback of the page. Not having any &lt;code&gt;alt&lt;/code&gt; tag would cause the same issue, as the screen reader assumes an &lt;code&gt;alt&lt;/code&gt; tag should be there and tries to find a substitute. An empty &lt;code&gt;alt&lt;/code&gt; tag will prevent both of these pitfalls.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;code&gt;alt&lt;/code&gt; tags shouldn't include "image of" or "graphic of"
&lt;/h4&gt;

&lt;p&gt;Another thought we might have, being the well-intentioned people we are, might be, "Hey, I should include 'image of' as part of my alt-text so that the user knows what's being read is a description of an image." Kudos for being thoughtful, but doing that would be unnecessary, repetitive, and redundant. Screen readers typically announce 'graphic' or 'image' before reading the &lt;code&gt;alt&lt;/code&gt; text.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj1t8ju7i897ezzzlwrwx.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj1t8ju7i897ezzzlwrwx.jpg" alt="Puppy and Goose as a Sample Image"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;(&lt;a href="https://commons.wikimedia.org/wiki/File:Retrieverwelpe_Apportieren.jpg" rel="noopener noreferrer"&gt;By mauser via Wikimedia Commons, CC-BY-SA 3.0&lt;/a&gt;)&lt;/em&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;!-- Don't Do This: --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"untitled_goose_puppy.jpg"&lt;/span&gt; &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;"Image of a Golden Retriever puppy carrying a plush goose toy."&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="c"&gt;&amp;lt;!-- Do This: --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"untitled_goose_puppy.jpg"&lt;/span&gt; &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;"Golden Retriever puppy carrying a plush goose toy."&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  &lt;code&gt;alt&lt;/code&gt; tags should be brief yet represent the content and function of the image
&lt;/h4&gt;

&lt;p&gt;Even though we may feel compelled to describe every minute detail of the image, or add a little pizzazz or extra tidbits of information into our alt-text, we shouldn't give in to that temptation. Our goal with alt-text is to briefly (in a few words or a sentence, no paragraphs here) summarize the information that a sighted user would glean by looking at the picture. If we still want to add something extra, we can always do that within the body of the text or a caption so that everyone else can enjoy our wit or insight.&lt;/p&gt;

&lt;p&gt;On the other hand, we must also be careful to include enough information that a screen reader user gets the same context and value from the image as a sighted user would. We shouldn't just describe the appearance of the image, we also explain what we intend the user to understand based on the image.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fow8x7jp4up29hqe52l0u.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fow8x7jp4up29hqe52l0u.jpeg" alt="Collapsed wooden house after earthquake to go with following code example"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;(&lt;a href="https://commons.wikimedia.org/wiki/File:BoulderCreekLomaPrietaEarthquake.jpeg" rel="noopener noreferrer"&gt;By J.K. Nakata, U.S. Geological Survey via Wikimedia Commons&lt;/a&gt;)&lt;/em&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;!-- Don't Do This: Too Much/Irrelevant Information --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"Loma_Prieta_Damage.jpg"&lt;/span&gt;
&lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;"A wood-framed house with an avant-garde split roof and ornate and beautiful wood panel siding and five glass windows across, collapsed onto a blue car following the Loma Prieta earthquake."&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="c"&gt;&amp;lt;!-- Also Don't Do This: Too Little Information --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"Loma_Prieta_Damage.jpg"&lt;/span&gt;
&lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;"A house collapsed onto a carport."&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="c"&gt;&amp;lt;!-- Do This: --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"Loma_Prieta_Damage.jpg"&lt;/span&gt;
&lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;"A wooden house collapsed sideways onto a carport, demonstrating how a lack of shear walls contributed to the failure of the structure."&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Additional Resources
&lt;/h3&gt;

&lt;p&gt;If, like me, you don't do well with the grey area of "there's no one right answer," and you're realizing that alt-text can be a very nuanced and complex topic, fear not! There's a fantastic resource for you to bookmark: &lt;a href="https://www.w3.org/WAI/tutorials/images/decision-tree/" rel="noopener noreferrer"&gt;An &lt;code&gt;alt&lt;/code&gt; Decision Tree&lt;/a&gt;. The Web Accessibility Initiative made narrowing down what we need to include as analytical and straightforward as possible with this flowchart. That resource references their in-depth &lt;a href="https://www.w3.org/WAI/tutorials/images/" rel="noopener noreferrer"&gt;Images Tutorial&lt;/a&gt;, where you can explore the topics I introduced here in greater detail and see more examples. I highly recommend checking this out too!&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>html</category>
      <category>a11y</category>
      <category>codenewbie</category>
    </item>
    <item>
      <title>Two Ways to Make Your Command Line Interfaces More Accessible</title>
      <dc:creator>Bianca Aspin</dc:creator>
      <pubDate>Wed, 15 Mar 2023 19:57:44 +0000</pubDate>
      <link>https://dev.to/baspin94/two-ways-to-make-your-command-line-interfaces-more-accessible-541k</link>
      <guid>https://dev.to/baspin94/two-ways-to-make-your-command-line-interfaces-more-accessible-541k</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Command Line Interfaces (CLIs) are an essential part of every developer's arsenal of tools, allowing them to perform repetitive tasks with greater speed and efficiency. Basic CLIs are also a typical first project when you're learning Python. They are an excellent way to practice using Python functions, solidify your understanding of control flow concepts like looping and conditional statements, and get experience writing scripts. So whether you're just starting out building your first command line application or developing the next big suite of developer tools, here are a couple of small ways to improve the accessibility of what you build.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Accessibility of CLIs
&lt;/h2&gt;

&lt;p&gt;CLIs are often considered inherently more accessible for screen reader users than web-based applications. After all, you don't need to worry about alt text for images and reading order when your entire app is text-based and proceeds linearly, and CLIs are already entirely keyboard-operated by nature.&lt;/p&gt;

&lt;p&gt;As it turns out, the simplicity of CLIs can be a double-edged sword for accessibility. Without the underlying structure I discussed in &lt;a href="https://dev.to/baspin94/an-introduction-to-screen-readers-and-html-accessibility-212c"&gt;my post about HTML accessibility&lt;/a&gt;, a screen reader user &lt;em&gt;has&lt;/em&gt; to scan through the output line-by-line instead of using its built-in shortcuts to jump to the parts that are most relevant to them. This wouldn't be so bad if the output were &lt;em&gt;only&lt;/em&gt; plain and simple text. However, in practice, CLIs often still contain many elements catered toward a sighted audience. These visual elements are distracting and tedious for a screen reader user to navigate.&lt;/p&gt;

&lt;h2&gt;
  
  
  Research Study
&lt;/h2&gt;

&lt;p&gt;Three Google user-experience researchers, Harini Sampath, Alice Merrick, and Andrew Macvean, published a study in 2021, &lt;a href="https://dl.acm.org/doi/fullHtml/10.1145/3411764.3445544" rel="noopener noreferrer"&gt;Accessibility of Command Line Interfaces&lt;/a&gt;, exploring the various issues that arise for screen reader users when interacting with CLIs. Based on insights gleaned from screen reader users participating in user interviews and a usability evaluation study, the authors made several recommendations for improving CLI accessibility. &lt;/p&gt;

&lt;p&gt;I highly recommend checking out the full article, which is packed with helpful information, including excerpts from interviews with the users themselves. In the following sections, I'll be delving into two of the recommendations made in this article.&lt;/p&gt;

&lt;h2&gt;
  
  
  Recommendations
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Let users bypass visual elements
&lt;/h3&gt;

&lt;p&gt;As developers, we constantly look for ways to improve our users' experience when using our apps. Our natural inclination will be to make what we create visually appealing to our users, and CLIs are no exception. If anything, the straightforward, 'bare bones' appearance of the output rendering in the terminal makes it all the more tempting to throw in an eye-catching element or two to better grab the user's eye. &lt;/p&gt;

&lt;p&gt;Without the ability to embed images, where can we turn to accomplish this task? ASCII art. ASCII art is frequently included in CLIs in some form. The purpose for having it varies.&lt;/p&gt;

&lt;p&gt;Sometimes, it's there to greet users with a decorative title at the launch of the app.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3taxwshz4weqruglic10.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3taxwshz4weqruglic10.png" alt="ASCII art logo saying "&gt;&lt;/a&gt;&lt;/p&gt;
A screen reader will announce this output as "star star star star star star star star star star star star..."



&lt;p&gt;Sometimes, it mimics a status or progress bar from a graphical user interface (GUI).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F376ljrsmx3blvdbyzs56.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F376ljrsmx3blvdbyzs56.png" alt="ASCII art depiction of a loading bar at 30%, written with a combination of full blocks and lightly shaded blocks"&gt;&lt;/a&gt;&lt;/p&gt;
A screen reader will announce this output as "full block full block full block light shade light shade light shade...30%"



&lt;p&gt;Sometimes, it's there to format data in the output to look more like a traditional table with grid lines and borders.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvod5fn36ew5usv8ucww9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvod5fn36ew5usv8ucww9.png" alt="Data output formatted as a table using ASCII art to add in gridlines and borders"&gt;&lt;/a&gt;&lt;/p&gt;
A screen reader will announce this output as "box drawings double down and right, box drawings double horizontal, box drawings double horizontal, box drawings double horizontal, box drawings double down and horizontal..."



&lt;p&gt;While this formatting can make CLI output more pleasant for a sighted user to read, it makes it exponentially more unpleasant for a screen reader user to take in. Without the underlying structure of an HTML page, there's no option for the screen reader to skip to the main content. Instead, the user must sit there while every individual symbol and character is read.&lt;/p&gt;

&lt;p&gt;Check out the video below for an example of how a screen reader parses through ASCII art. The first 20 seconds should be more than enough to give you an idea of the problems ASCII output can pose for screen reader users.&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/yir99BwbSx4"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Fear not, though! You don't need to overhaul your app to remove that ASCII logo you painstakingly hand-coded. We can get around this issue by building some logic at the beginning of the app to check whether the user wants these visual enhancements. Then, we can conditionally render the visual elements based on the user's response to that prompt. Here's one approach:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Open your app with a plain text greeting.&lt;/li&gt;
&lt;li&gt;Initialize a variable to hold the user's viewing selection.&lt;/li&gt;
&lt;li&gt;Prompt the user to choose their viewing experience (confirm if they would like to view the app in 'plain text mode' or words to that effect, and describe what that means).&lt;/li&gt;
&lt;li&gt;Update the 'viewing selection' variable you initialized earlier, and print a confirmation message that the user has opted for plain text mode.&lt;/li&gt;
&lt;li&gt;Wrap any purely visual elements like ASCII art, decorative lines, and table formatting in a conditional statement, to render only if 'viewing selection' variable is false.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here's what this approach looks like in practice:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# imports, database initialization, etc...
&lt;/span&gt;
&lt;span class="c1"&gt;# These lists help with data validation throughout the app:
&lt;/span&gt;&lt;span class="n"&gt;YES&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;y&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;ye&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;yes&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;NO&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;n&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;no&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;

&lt;span class="c1"&gt;# Start with a plain text greeting instead of the ASCII art:
&lt;/span&gt;&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Welcome to My Totally Epic CLI!&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Initialize a variable for the user's viewing selection:
&lt;/span&gt;&lt;span class="n"&gt;plain_text_mode&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;

&lt;span class="c1"&gt;# Prompt user to choose viewing experience:
&lt;/span&gt;&lt;span class="n"&gt;plain_select&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;input&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'''&lt;/span&gt;&lt;span class="s"&gt;
Would you prefer to use this app in plain text mode
(with visual elements and decorations removed)?
Enter &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Y&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt; for &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Yes,&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt; &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;N&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt; for &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;No&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;: &lt;/span&gt;&lt;span class="sh"&gt;'''&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Update the variable you initialized earlier.
# Print a confirmation message that 'plain text mode' is active.
&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;plain_select&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;lower&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;YES&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;plain_text_mode&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Plain text mode selected.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# If 'no' is selected, visual elements you preface with 
# 'if not plain_text_mode' will be displayed: 
&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;plain_text_mode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'''&lt;/span&gt;&lt;span class="s"&gt;
    # Your beautiful ASCII art goes in here!
    &lt;/span&gt;&lt;span class="sh"&gt;'''&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Let users export tables to CSV
&lt;/h3&gt;

&lt;p&gt;Tables were already mentioned in the previous section for how they are formatted in CLI output. However, even without the distracting noise of those extra characters forming the table's borders, tables still pose a problem for screen readers. That lack of any underlying structure is back to cause issues, as the screen reader has no landmarks to anchor itself, like header rows and row boundaries. This means that screen reader users essentially have to pick out how many columns there are, memorize what each column represents, and then try to keep track of which column is being read at any time as they navigate through the table cell-by-cell, line-by-line.&lt;/p&gt;

&lt;p&gt;When users in the &lt;a href="https://dl.acm.org/doi/fullHtml/10.1145/3411764.3445544" rel="noopener noreferrer"&gt;Google study&lt;/a&gt; were asked how their CLI table viewing experience could be improved, they pointed to the ability to export these tables in another format that their screen reader could better navigate, such as a CSV file, as a better experience.&lt;/p&gt;

&lt;p&gt;We can use &lt;a href="https://docs.python.org/3/library/csv.html" rel="noopener noreferrer"&gt;Python's csv module&lt;/a&gt; to write data to its own CSV file right from within our CLI application. Once we've imported the csv module, here is how we would go about writing the results of a database query to their own csv file:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use &lt;a href="https://docs.python.org/3/library/functions.html#open" rel="noopener noreferrer"&gt;open()&lt;/a&gt; to specify a path for the new file and open it in 'write' mode.&lt;/li&gt;
&lt;li&gt;Create a list containing the fields returned by the query.&lt;/li&gt;
&lt;li&gt;Create a new instance of the &lt;a href="https://docs.python.org/3/library/csv.html#csv.DictWriter" rel="noopener noreferrer"&gt;DictWriter class&lt;/a&gt;, which converts dictionaries into rows in the csv file.&lt;/li&gt;
&lt;li&gt;Use DictWriter's &lt;a href="https://docs.python.org/3/library/csv.html#csv.DictWriter.writeheader" rel="noopener noreferrer"&gt;writeheader()&lt;/a&gt; method to write the field names from the list to the csv file.&lt;/li&gt;
&lt;li&gt;Iterate through the records returned by your query and use DictWriter's &lt;a href="https://docs.python.org/3/library/csv.html#csv.csvwriter.writerow" rel="noopener noreferrer"&gt;writerow()&lt;/a&gt; method to write each record to the csv file.&lt;/li&gt;
&lt;li&gt;Use close() to finish editing and close the csv file.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here's what this approach looks like in practice:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Import the csv module:
&lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;CSV&lt;/span&gt;

&lt;span class="c1"&gt;# Perform your database query:
&lt;/span&gt;&lt;span class="n"&gt;pets&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Pet&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Pet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;owner_id&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;owner_id&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="c1"&gt;# Name the file and open it in 'write' mode:
&lt;/span&gt;&lt;span class="n"&gt;pets_csv&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;./csv_output/your_pets.csv&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mode&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;w&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Create a list containing the fields returned by the query.
&lt;/span&gt;&lt;span class="n"&gt;fields&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Pet ID&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Age&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Breed&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Temperament&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Treats&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Notes&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Owner ID&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="c1"&gt;# Create an instance of DictWriter:
&lt;/span&gt;&lt;span class="n"&gt;write_pets&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;csv&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;DictWriter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pets_csv&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;fieldnames&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;fields&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Use DictWriter to create a header row in your CSV file:
&lt;/span&gt;&lt;span class="n"&gt;write_pets&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;writeheader&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="c1"&gt;# Iterate through the records returned by the query.
# Use DictWriter to create a row for each of those records:
&lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;pet&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;pets&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;write_pets&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;writerow&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
       &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Pet ID&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;pet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
       &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;pet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
       &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Age&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;pet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;age&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
       &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Breed&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;pet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;breed&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
       &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Temperament&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;pet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;temperament&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
       &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Treats&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;pet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;favorite_treats&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
       &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Notes&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;pet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;notes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
       &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Owner ID&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;pet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;owner_id&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="c1"&gt;# Finish editing and close the csv file:
&lt;/span&gt;&lt;span class="n"&gt;pets_csv&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This gets our tabular data into a CSV file, but at this point, the user will still need to locate and open this file. We can save them that step by adding functionality to open that file in their default system viewer once it has been closed. This step gets a bit more complicated, since now we have to work around different operating systems, but thanks to this &lt;a href="https://stackoverflow.com/questions/434597/open-document-with-default-os-application-in-python-both-in-windows-and-mac-os" rel="noopener noreferrer"&gt;StackOverflow post about opening files in the system default viewer&lt;/a&gt;, we have a way to do it! &lt;/p&gt;

&lt;p&gt;We'll need to import Python's os, subprocess, and platform modules to help. What these modules will do in a nutshell: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://docs.python.org/3/library/os.html?highlight=os#module-os" rel="noopener noreferrer"&gt;os&lt;/a&gt; allows us to tap into the user's operating system dependent functionality.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.python.org/3/library/subprocess.html?highlight=subprocess#module-subprocess" rel="noopener noreferrer"&gt;subprocess&lt;/a&gt; allows us to start a new process on the user's device (opening their spreadsheet software, in this case).&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.python.org/3/library/platform.html?highlight=platform#module-platform" rel="noopener noreferrer"&gt;platform&lt;/a&gt; provides us with identifying information for the user's platform (Mac, Windows, or Linux).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With those modules imported, here's how we can build out a helper function to check the user's operating system and launch our new csv file in their default app for spreadsheets:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;subprocess&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;platform&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;file_opener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;filepath&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;

&lt;span class="c1"&gt;# MacOS
&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;platform&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;system&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Darwin&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;

    &lt;span class="n"&gt;subprocess&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;open&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;filepath&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="c1"&gt;# Windows
&lt;/span&gt;&lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;platform&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;system&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Windows&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;

    &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;startfile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;filepath&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Linux
&lt;/span&gt;&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;subprocess&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;xdg-open&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;filepath&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;With this helper function built out, all we have left to do is call it after we've closed the file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;
&lt;span class="n"&gt;pets_csv&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="nf"&gt;file_opener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;./csv_output/your_pets.csv&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;And with that, our data will now open up in the user's spreadsheet software, ready to be read more efficiently by their screen reader!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9yjhhrzpx3g05o3r1duw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9yjhhrzpx3g05o3r1duw.png" alt="A screenshot of a CSV containing pet data opened in Microsoft Excel"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>python</category>
      <category>a11y</category>
      <category>codenewbie</category>
      <category>beginners</category>
    </item>
    <item>
      <title>An Introduction to Screen Readers and HTML Accessibility</title>
      <dc:creator>Bianca Aspin</dc:creator>
      <pubDate>Wed, 15 Feb 2023 05:41:54 +0000</pubDate>
      <link>https://dev.to/baspin94/an-introduction-to-screen-readers-and-html-accessibility-212c</link>
      <guid>https://dev.to/baspin94/an-introduction-to-screen-readers-and-html-accessibility-212c</guid>
      <description>&lt;p&gt;&lt;em&gt;What are screen readers, how do they navigate a website, and how can we make our HTML more screen reader-friendly?&lt;/em&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Screen Readers and Accessibility
&lt;/h2&gt;

&lt;p&gt;Chances are good you've heard something about screen readers already in your programming journey. It's often mentioned when you're first learning how to embed images into an HTML document, in the context of adding alt tags to images. (I'll explore alt tags more in an upcoming post.) What often isn't discussed is what a screen reader is.&lt;/p&gt;

&lt;p&gt;A &lt;a href="https://en.wikipedia.org/wiki/Screen_reader" rel="noopener noreferrer"&gt;screen reader&lt;/a&gt; is software that lets a blind or visually-impaired user consume information from a computer screen in another format, like audio or braille.&lt;/p&gt;

&lt;p&gt;One common misconception is that screen readers are simply text-to-speech software. While synthesized speech is a component of any screen reader, it is only one of several features. A user might not even use this audio feedback. They could connect a &lt;a href="https://en.wikipedia.org/wiki/Refreshable_braille_display" rel="noopener noreferrer"&gt;refreshable braille display&lt;/a&gt; to render the screen reader's output instead. A screen reader is also far more than a "reader"—it's a tool for navigating and using a computer. Screen readers don’t merely repeat the text on the screen, they interpret visual cues—like images, links, buttons, headings, menus, and forms—and allow users to interact with those elements.&lt;/p&gt;

&lt;p&gt;Before we get much further, an example of this technology in action would be helpful. Marc Sutton of the University of California San Francisco created an excellent demonstration of how a screen reader navigates a site back in 2016. Take a couple of minutes now to watch this brief demo. &lt;em&gt;(Note: At the end of the video, Marc demonstrates some issues with HTML tables. We won't be discussing those in this post; tables are another topic warranting a post of their own.)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/dEbl5jvLKGQ"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;In the video, Marc shows how a screen reader user can use built-in commands to navigate. These shortcuts let users scan a webpage and drill down on areas of interest. Users can jump around to different sections using headings and can also listen to a list of links pulled from the page to find what they're looking for quickly.&lt;/p&gt;

&lt;p&gt;A screen reader is a very powerful tool to have at one's disposal. However, it can only perform these handy shortcuts if a page has the proper underlying structure.&lt;/p&gt;

&lt;p&gt;Here are three essential areas to consider when building a new HTML document. These steps will help screen reader users easily navigate our page without spending hours reading through our content line-by-line to find what they need.&lt;/p&gt;

&lt;h2&gt;
  
  
  Steps for Improving Screen Reader Accessibility
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Include a Descriptive Page Title
&lt;/h3&gt;

&lt;p&gt;The first step we can take when setting up an accessible HTML document starts at the top: the page's title itself. &lt;/p&gt;

&lt;p&gt;The 'title' I'm referring to in this case is the one that displays within your browser's tabs or along the top of the window. It's defined using the &lt;code&gt;&amp;lt;title&amp;gt;&lt;/code&gt; tag in the &lt;code&gt;&amp;lt;head&amp;gt;&lt;/code&gt; (metadata) section of an HTML document.&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;link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"stylesheet"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text/css"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"style.css"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="c"&gt;&amp;lt;!--This is where you'll define the page title:--&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;Title&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;/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;&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%2Fwq5uklon6ozdko8sbrob.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%2Fwq5uklon6ozdko8sbrob.png" alt="Site Title Within Chrome Browser Tab" width="675" height="80"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The title serves an essential purpose for screen reader users. It's the first thing the screen reader announces upon opening a page or switching to that page from a different tab. A sighted user might decide whether to read a page by giving it a quick scan from top to bottom. This kind of scanning takes longer to do with a screen reader. Well-written titles allow screen reader users to identify the general content quickly. From there, they can decide whether to venture further into the page.&lt;/p&gt;

&lt;p&gt;First, each &lt;code&gt;&amp;lt;title&amp;gt;&lt;/code&gt; within a site should be unique. If we have many pages within one of our sites, they shouldn't all have the same title. Without a way to tell one page apart from another, a screen reader user will have to go further into the page to know its contents, which is time-consuming. &lt;/p&gt;

&lt;p&gt;Relatedly, &lt;code&gt;&amp;lt;title&amp;gt;&lt;/code&gt; should be front-loaded, putting the most relevant and unique identifying information first. That way, a screen reader user only needs to spend as long as necessary to find out what's on that page.&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;!-- Back-Loaded Version (Avoid This) --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;Dunder Mifflin Paper Company | Contact Us&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;

&lt;span class="c"&gt;&amp;lt;!-- Front-Loaded Version (Do This) --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;Contact Us | Dunder Mifflin Paper Company &lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This practice also helps sighted users distinguish one page from the other if they have many tabs from your site open at once.&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%2Ft7moil9kubxe59c4h2kx.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%2Ft7moil9kubxe59c4h2kx.png" alt="Multiple Tabs Open Within Chrome Browser" width="683" height="75"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;While we strive to make each &lt;code&gt;&amp;lt;title&amp;gt;&lt;/code&gt; unique and descriptive, we should also keep them brief. A good rule of thumb is to keep the length of a title under 60 characters.&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;!--Longer Version - 124 Characters (Avoid This) --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;Michael Scott's Dunder Mifflin Scranton Meredith Palmer Memorial Celebrity Rabies Awareness Pro-Am Fun Run Race For the Cure&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;

&lt;span class="c"&gt;&amp;lt;!--Shorter Version -- 51 Characters (Do This) --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;Charity Race for the Cure | Dunder Mifflin&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Provide a Meaningful Hierarchy with Headings
&lt;/h3&gt;

&lt;p&gt;A screen reader user listens to our descriptive page title and decides they want to explore it in more detail. Their next step might be to skim the page for a high-level view of what's there. They can do this by jumping between any heading tags (&lt;code&gt;&amp;lt;h1&amp;gt;&lt;/code&gt; through &lt;code&gt;&amp;lt;h6&amp;gt;&lt;/code&gt;) we've included on our page.&lt;/p&gt;

&lt;p&gt;Headings organize our page, giving screen reader users another way to orient themselves to its contents. A screen reader user might start by reading all the level 1 (&lt;code&gt;&amp;lt;h1&amp;gt;&lt;/code&gt;) headings in the document. They could then choose to drill down further into a section and read through all the level 2 (&lt;code&gt;&amp;lt;h2&amp;gt;&lt;/code&gt;) headings there, then all the level 3 (&lt;code&gt;&amp;lt;h3&amp;gt;&lt;/code&gt;) headings, and so on.&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;body&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;Heading Level 1&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt; &lt;span class="c"&gt;&amp;lt;!-- Reading Order: 1 --&amp;gt;&lt;/span&gt;

        &lt;span class="nt"&gt;&amp;lt;h2&amp;gt;&lt;/span&gt;Heading Level 2&lt;span class="nt"&gt;&amp;lt;/h2&amp;gt;&lt;/span&gt; &lt;span class="c"&gt;&amp;lt;!-- Reading Order: 2 --&amp;gt;&lt;/span&gt;

            &lt;span class="nt"&gt;&amp;lt;h3&amp;gt;&lt;/span&gt;Heading Level 3&lt;span class="nt"&gt;&amp;lt;/h3&amp;gt;&lt;/span&gt; &lt;span class="c"&gt;&amp;lt;!-- Skipped --&amp;gt;&lt;/span&gt;

        &lt;span class="nt"&gt;&amp;lt;h2&amp;gt;&lt;/span&gt;Heading Level 2&lt;span class="nt"&gt;&amp;lt;/h2&amp;gt;&lt;/span&gt; &lt;span class="c"&gt;&amp;lt;!-- Reading Order: 3 --&amp;gt;&lt;/span&gt;

            &lt;span class="nt"&gt;&amp;lt;h3&amp;gt;&lt;/span&gt;Heading Level 3&lt;span class="nt"&gt;&amp;lt;/h3&amp;gt;&lt;/span&gt; &lt;span class="c"&gt;&amp;lt;!-- Reading Order: 4 --&amp;gt;&lt;/span&gt;

            &lt;span class="nt"&gt;&amp;lt;h3&amp;gt;&lt;/span&gt;Heading Level 3&lt;span class="nt"&gt;&amp;lt;/h3&amp;gt;&lt;/span&gt; &lt;span class="c"&gt;&amp;lt;!-- Reading Order: 5 --&amp;gt;&lt;/span&gt;

            &lt;span class="nt"&gt;&amp;lt;h3&amp;gt;&lt;/span&gt;Heading Level 3&lt;span class="nt"&gt;&amp;lt;/h3&amp;gt;&lt;/span&gt; &lt;span class="c"&gt;&amp;lt;!-- Reading Order: 6 --&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can assist with this workflow by having headings in the first place. Without them, we're handing our screen reader users a wall of text they'll have to listen to line-by-line to find what they need. &lt;/p&gt;

&lt;p&gt;Beyond having headings, we should ensure they work together to create a meaningful hierarchy. &lt;/p&gt;

&lt;p&gt;To do this, it's a good practice only to have one &lt;code&gt;&amp;lt;h1&amp;gt;&lt;/code&gt; element in the document, which serves as the title for our page. That &lt;code&gt;&amp;lt;h1&amp;gt;&lt;/code&gt; could even be the same as the &lt;code&gt;&amp;lt;title&amp;gt;&lt;/code&gt; element in the head. Then, our &lt;code&gt;&amp;lt;h2&amp;gt;&lt;/code&gt; elements can serve as our top-level section headings. If we need to get more granular within each section, we can use &lt;code&gt;&amp;lt;h3&amp;gt;&lt;/code&gt; through &lt;code&gt;&amp;lt;h6&amp;gt;&lt;/code&gt; as needed.&lt;/p&gt;

&lt;p&gt;When laying out our hierarchy, we mustn't skip headings. &lt;code&gt;&amp;lt;h1&amp;gt;&lt;/code&gt; should only be followed by &lt;code&gt;&amp;lt;h2&amp;gt;&lt;/code&gt;, which should only be followed by &lt;code&gt;&amp;lt;h3&amp;gt;&lt;/code&gt;, etc. Skipping headings (say, by moving from &lt;code&gt;&amp;lt;h1&amp;gt;&lt;/code&gt; into an &lt;code&gt;&amp;lt;h3&amp;gt;&lt;/code&gt;) could confuse screen reader users, who might wonder if they accidentally skipped a heading.&lt;/p&gt;

&lt;p&gt;For the heading text itself, the same rule of thumb we can apply to page titles also applies here -- keep it unique, brief, and descriptive.&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;h1&amp;gt;&lt;/span&gt;Michael Scott Autobiography&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;

&lt;span class="c"&gt;&amp;lt;!--Don't Do This: --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;h2&amp;gt;&lt;/span&gt;Part 1&lt;span class="nt"&gt;&amp;lt;/h2&amp;gt;&lt;/span&gt; &lt;span class="c"&gt;&amp;lt;!-- Not unique or descriptive --&amp;gt;&lt;/span&gt;

&lt;span class="c"&gt;&amp;lt;!--Instead, Do This: --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;h2&amp;gt;&lt;/span&gt;My Childhood&lt;span class="nt"&gt;&amp;lt;/h2&amp;gt;&lt;/span&gt; &lt;span class="c"&gt;&amp;lt;!-- Describes topic for section --&amp;gt;&lt;/span&gt;

&lt;span class="c"&gt;&amp;lt;!--Don't Do This: --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;h2&amp;gt;&lt;/span&gt;My philosophy is, basically this. And this is something that I live by. And I always have. And I always will. Don’t, ever, for any reason, do anything, to anyone, for any reason, ever, no matter what, no matter where, or who you are with, or, or where you are going, or, or where you’ve been. Ever. For any reason. Whatsoever.&lt;span class="nt"&gt;&amp;lt;/h2&amp;gt;&lt;/span&gt; &lt;span class="c"&gt;&amp;lt;!-- Not brief --&amp;gt;&lt;/span&gt;

&lt;span class="c"&gt;&amp;lt;!--Do This: --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;h2&amp;gt;&lt;/span&gt;My Philosophy&lt;span class="nt"&gt;&amp;lt;/h2&amp;gt;&lt;/span&gt; &lt;span class="c"&gt;&amp;lt;!-- Brief summary of section topic --&amp;gt;&lt;/span&gt;
&lt;span class="c"&gt;&amp;lt;!--Move the rest to the actual text content of the section. --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;My philosophy is, basically this. And this is something that I live by. And I always have. And I always will. Don’t, ever, for any reason, do anything, to anyone, for any reason, ever, no matter what, no matter where, or who you are with, or, or where you are going, or, or where you’ve been. Ever. For any reason. Whatsoever.&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;A common issue I've seen with heading tags is using them for styling purposes, like font sizing. Perhaps &lt;code&gt;&amp;lt;h2&amp;gt;&lt;/code&gt; feels too big, and the size of &lt;code&gt;&amp;lt;h3&amp;gt;&lt;/code&gt; fits better for our aesthetic. Perhaps the boldness of an &lt;code&gt;&amp;lt;h1&amp;gt;&lt;/code&gt; heading is what we're looking for to bring attention to a quote or essential information. In either case, the answer isn't to use a different heading level. This will otherwise lead to a disjointed reading experience for our screen reader users. Instead, we should change the styling within our CSS and stick to using heading tags for page organization.&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;body&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;Michael Scott Autobiography&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt; &lt;span class="c"&gt;&amp;lt;!-- Reading Order: 1 --&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;h2&amp;gt;&lt;/span&gt;My Childhood&lt;span class="nt"&gt;&amp;lt;/h2&amp;gt;&lt;/span&gt; &lt;span class="c"&gt;&amp;lt;!-- Skipped --&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;When I discovered YouTube, 
        I didn’t work for five days.&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt; &lt;span class="c"&gt;&amp;lt;!-- Skipped --&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;h2&amp;gt;&lt;/span&gt;My Career&lt;span class="nt"&gt;&amp;lt;/h2&amp;gt;&lt;/span&gt; &lt;span class="c"&gt;&amp;lt;!-- Skipped --&amp;gt;&lt;/span&gt;

        &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;I am Beyoncé, always.&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt; &lt;span class="c"&gt;&amp;lt;!-- Skipped --&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;h2&amp;gt;&lt;/span&gt;My Philosophy&lt;span class="nt"&gt;&amp;lt;/h2&amp;gt;&lt;/span&gt; &lt;span class="c"&gt;&amp;lt;!-- Skipped --&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;"You miss 100% of the shots you don't take. -Wayne Gretsky" -Michael Scott&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt; &lt;span class="c"&gt;&amp;lt;!-- Reading Order: 2 --&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;My philosophy is, basically this. And this is something that I live by. And I always have. And I always will. Don’t, ever, for any reason, do anything, to anyone, for any reason, ever, no matter what, no matter where, or who you are with, or, or where you are going, or, or where you’ve been. Ever. For any reason. Whatsoever.&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt; &lt;span class="c"&gt;&amp;lt;!-- Reading Order: 3 --&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;/body&amp;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/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F20bopqp7vpurg73vf4kq.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%2F20bopqp7vpurg73vf4kq.png" alt="Disjointed Reading Order Caused by Misused Headings" width="800" height="216"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Give Context with Link Text
&lt;/h3&gt;

&lt;p&gt;Screen reader users can also get a sense of a page's content using the "list all links" shortcut built into their software. This allows them to skip around the different hyperlinks embedded into the page, which we've coded using &lt;code&gt;&amp;lt;a&amp;gt;&lt;/code&gt; tags.&lt;/p&gt;

&lt;p&gt;This shortcut is only as powerful as the text we provide within the &lt;code&gt;&amp;lt;a&amp;gt;&lt;/code&gt;, as that is what the screen reader announces. The most common pitfall here is using vague text for links, such as "click here," "here," "read more, "more," or "link."&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;h1&amp;gt;&lt;/span&gt;Sales Team Directory - Dunder Mifflin Scranton&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;ul&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&lt;/span&gt;Dwight Schrute | Email: &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;"mailto:dwightschrute@dundermifflin.com"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Click Here&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&lt;/span&gt;Jim Halpert | Email: &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;"mailto:jimhalpert@dundermifflin.com"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Click Here&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&lt;/span&gt;Andy Bernard | Email: &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;"mailto:andybernard@dundermifflin.com"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Click Here&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&lt;/span&gt;Stanley Hudson | Email: &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;"mailto:stanleyhudson@dundermifflin.com"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Click Here&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&lt;/span&gt;Phyllis Vance | Email: &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;"mailto:phyllisvance@dundermifflin.com"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Click Here&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;/ul&amp;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/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2c2oc0v2qzifn8l0oka7.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%2F2c2oc0v2qzifn8l0oka7.png" alt="Staff Directory With Many Links Saying 'Click Here'" width="682" height="176"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The same standard we've followed for the text within our &lt;code&gt;&amp;lt;title&amp;gt;&lt;/code&gt; and heading elements applies to &lt;code&gt;&amp;lt;a&amp;gt;&lt;/code&gt; elements: keep them meaningful but brief. Users should understand where the link will take them without the context of the surrounding text. Here is how the same directory could be more screen reader-friendly.&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;h1&amp;gt;&lt;/span&gt;Sales Team Directory - Dunder Mifflin Scranton&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;ul&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&lt;/span&gt;Dwight Schrute | &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;"mailto:dwightschrute@dundermifflin.com"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Email Dwight&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&lt;/span&gt;Jim Halpert | &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;"mailto:jimhalpert@dundermifflin.com"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Email Jim&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&lt;/span&gt;Andy Bernard | &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;"mailto:andybernard@dundermifflin.com"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Email Andy&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&lt;/span&gt;Stanley Hudson | &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;"mailto:stanleyhudson@dundermifflin.com"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Email Stanley&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&lt;/span&gt;Phyllis Vance | &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;"mailto:phyllisvance@dundermifflin.com"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Email Phyllis&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;/ul&amp;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/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhrkmb5k800cemhn2eiea.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%2Fhrkmb5k800cemhn2eiea.png" alt="Staff Directory Revised With Descriptive Links" width="664" height="173"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If we find ourselves saying, "for XYZ, click here," chances are good we could revise that down to "XYZ" for our link text.&lt;/p&gt;

&lt;p&gt;One practice to avoid is using the URL itself as the link text. Unless the link is very basic (e.g., &lt;code&gt;wikipedia.org&lt;/code&gt;), a URL is neither brief nor meaningful when read by a screen reader. Instead, it will read like a jumble of characters.&lt;/p&gt;

&lt;p&gt;Another practice to avoid is making a link out of an entire paragraph (say, if we wanted to reference a website we pulled a quote from). The screen reader will read that whole passage as part of the link list.&lt;/p&gt;

&lt;h2&gt;
  
  
  Further Reading
&lt;/h2&gt;

&lt;p&gt;The steps outlined above are not exhaustive -- implementing them all does not automatically make our page accessible. However, they are a good start.&lt;/p&gt;

&lt;p&gt;For additional information, check out the MDN docs for each element discussed above. Each has a section about accessibility.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/title#accessibility_concerns" rel="noopener noreferrer"&gt;&lt;code&gt;&amp;lt;title&amp;gt;&lt;/code&gt; tag accessibility&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/Heading_Elements#accessibility_concerns" rel="noopener noreferrer"&gt;Section heading accessibility&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/a#accessibility" rel="noopener noreferrer"&gt;&lt;code&gt;&amp;lt;a&amp;gt;&lt;/code&gt;tag accessibility&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>watercooler</category>
    </item>
    <item>
      <title>Web Accessibility Basics for Beginners</title>
      <dc:creator>Bianca Aspin</dc:creator>
      <pubDate>Wed, 15 Feb 2023 05:41:05 +0000</pubDate>
      <link>https://dev.to/baspin94/web-accessibility-basics-for-beginner-developers-5c8j</link>
      <guid>https://dev.to/baspin94/web-accessibility-basics-for-beginner-developers-5c8j</guid>
      <description>&lt;p&gt;&lt;em&gt;What is web accessibility, why is it important, and why should we start learning about it now when we're just starting ourselves?&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;Disclaimer: This first blog post in the series will be more philosophical than the other posts in the series. I'll be providing context for the more technical lessons we'll dive into in later posts.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why I'm Interested in Web Accessibility
&lt;/h2&gt;

&lt;p&gt;First, you should know that anytime I say "beginner developer," I'm also referring to myself. I began my journey toward a new career in software development recently. I've been drawn toward this field for many years, though. So what started me down this path? Accessibility.&lt;/p&gt;

&lt;p&gt;Before programming, I spent seven years working in a college disability resources department. I helped students work around barriers posed by course materials not designed with differing abilities in mind. Those students, in turn, taught me a great deal about what ‘accessibility’ means for users. I discovered how widespread accessibility issues are in the apps and tools many of us take for granted. &lt;/p&gt;

&lt;p&gt;Here's a small sample of the problems my students and I encountered:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;A publisher's proprietary software students had to use to read their digital textbooks (the only format available). It claimed to be "accessible" but lacked the proper structure for screen readers to navigate effectively.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Course management systems that were too cluttered and complicated. This made it difficult for someone with any issues with executive functioning to keep track of courses and assignments.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A billion-dollar company's popular statistical analysis software. Users could not adjust the font size of the minuscule numbers on the screen.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In each of these situations, inaccessible technology made life harder for students. Working around these issues created more work for them to get things done. The extra effort needed put them on unequal footing with their peers. For instance, in the last example I shared, the only workaround available for this student with low vision was using the screen magnification settings built into their laptop. This required them to learn a new way of navigating not just the program, but also their computer with the many keyboard shortcuts needed. All this on top of learning statistics (of all the difficult subjects)!&lt;/p&gt;

&lt;p&gt;I was frustrated on behalf of my students. Technology was supposedly "the great equalizer," yet it seemed to create more issues than it resolved. Moreover, when working with the vendors, it seemed like all they could offer me were more workarounds and not actual accessibility solutions.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why I'm Writing This Blog
&lt;/h2&gt;

&lt;p&gt;With all this, I became curious to learn more about what happens “under the hood” that makes a given piece of technology ‘accessible’ (or not).&lt;/p&gt;

&lt;p&gt;Of course, just as if I were to open up an actual car hood to see what was happening underneath, I was perplexed and overwhelmed when I took that first look. How are all these parts connected? How do they work together? Where is that leak coming from? I felt that way as an end user trying to find solutions for my students. I still feel that way now that I have some knowledge of software development, but at least now, I have more context.&lt;/p&gt;

&lt;p&gt;I hope to provide you with a better understanding of that context by sharing my thoughts and findings in this blog. I'm learning the nuts and bolts of how this works with you.&lt;/p&gt;

&lt;p&gt;Before we go further, let's talk more about what "accessibility" means on the web.&lt;/p&gt;

&lt;h2&gt;
  
  
  Accessibility in a Nutshell
&lt;/h2&gt;

&lt;p&gt;To make a webpage accessible is to ensure that anyone can use it, whether or not they have a disability.&lt;/p&gt;

&lt;p&gt;As it turns out, people with disabilities constitute much of our potential userbase. The Centers for Disease Control and Prevention estimate that around 1 in 4 adults (26%) in the United States experience a disability. The World Health Organization puts this statistic at 1 in 6 people (16%) worldwide. (See the &lt;a href="https://www.cdc.gov/ncbddd/disabilityandhealth/infographic-disability-impacts-all.html#:~:text=Up%20to%201%20in%204,have%20some%20type%20of%20disability."&gt;'CDC's Disability Impacts All of Us' infographic&lt;/a&gt; and the &lt;a href="https://www.who.int/news-room/fact-sheets/detail/disability-and-health"&gt;WHO's 'Disability' fact sheet&lt;/a&gt; for other statistics related to disability in the US and worldwide.)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Disability&lt;/strong&gt; covers the many physical and mental conditions impacting mobility, cognition, independent living, hearing, vision, and self-care. It's a broad category, and there are a wide variety of barriers users with disabilities may encounter when accessing content on the web. Because of this, there is no concrete definition or standard that says, "my page is now accessible." Accessibility is not a one-and-done checklist item but an ongoing process. But, thanks to the World Wide Web Consortium (W3C)'s Web Accessibility Initiative, we do have several helpful guidelines—the &lt;a href="https://www.w3.org/WAI/standards-guidelines/wcag/"&gt;Web Content Accessibility Guidelines (WCAG)&lt;/a&gt; to be precise.&lt;/p&gt;

&lt;p&gt;The guidelines themselves are dense and technical, so you don't need to dive too deep down this rabbit hole yet as a beginner developer—for today, know they exist. (As an interim resource, MDN has a set of helpful articles unpacking various aspects of WCAG, &lt;a href="https://developer.mozilla.org/en-US/docs/Web/Accessibility/Understanding_WCAG"&gt;Understanding the Web Content Accessibility Guidelines&lt;/a&gt;.)&lt;/p&gt;

&lt;p&gt;However, now is the perfect time to start thinking about WCAG's four user-centered principles of accessibility, also known as POUR.&lt;/p&gt;

&lt;h2&gt;
  
  
  Our Goal: Design POUR Websites
&lt;/h2&gt;

&lt;p&gt;To be accessible, our websites should be:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt; &lt;strong&gt;P&lt;/strong&gt;erceivable&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;O&lt;/strong&gt;perable&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;U&lt;/strong&gt;nderstandable&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;R&lt;/strong&gt;obust&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's unpack these principles a bit.&lt;/p&gt;

&lt;h3&gt;
  
  
  Perceivable
&lt;/h3&gt;

&lt;p&gt;Users should be able to take in our content even if they're missing one or more of their senses: sight, hearing, or touch (as of this writing, smell and taste are not used on the web—yet...).&lt;/p&gt;

&lt;p&gt;Two examples of making content perceivable are providing captions for audio and video content and alt text or image descriptions for visual content.&lt;/p&gt;

&lt;h3&gt;
  
  
  Operable
&lt;/h3&gt;

&lt;p&gt;Users should be able to enter inputs and interact with our content regardless of which hardware they use (keyboard, mouse, screen reader, mouth stick, etc.).&lt;/p&gt;

&lt;p&gt;One example of making content operable is ensuring that all of a site's functionality is accessible using a keyboard alone. Another consideration would be testing that the site functions as expected in both mobile and desktop environments. We don't want to exclude users whose disability makes navigating the web easier on a handheld device such as a tablet or phone.&lt;/p&gt;

&lt;h3&gt;
  
  
  Understandable
&lt;/h3&gt;

&lt;p&gt;Users should easily know how to interact with our site.&lt;/p&gt;

&lt;p&gt;Some examples of making content more understandable include using as plain language as possible—particularly when giving instructions on how to interact with the site—laying out content consistently and logically, and ensuring that any interactive elements like forms are labeled clearly and work predictably.&lt;/p&gt;

&lt;h3&gt;
  
  
  Robust
&lt;/h3&gt;

&lt;p&gt;Users should be able to interact with our content regardless of which browser, plug-ins, and assistive technology they use.&lt;/p&gt;

&lt;p&gt;One example of how this comes up: our users may be most familiar with using their assistive technology in one browser in particular. As developers, we'll want to ensure our content is cross-browser-compatible.&lt;/p&gt;

&lt;p&gt;For more information about the POUR principles of design, I recommend looking at the nonprofit accessibility advocacy group WebAIM's library of resources (which you may find easier to digest than the raw standards themselves), including their article &lt;a href="https://webaim.org/articles/pour/"&gt;Constructing a POUR Website&lt;/a&gt;. I'll revisit these principles as we explore more technical content in the following blogs.&lt;/p&gt;

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

&lt;p&gt;Programming and web accessibility are both complex. Trying to make sense of either of them on their own can be intimidating. If you're reading this, you're already working through figuring out that programming one. Yet, even though that accessibility piece looks daunting, and we already feel like we have our hands full with just getting our first lines of code to work, as beginner developers we should start wrapping our heads around these concepts now. We want to get into good habits early and make sure everyone can enjoy the things we create. I've learned from experience that it's much easier to make something accessible from the start than to make it more accessible later on. More importantly, accessibility is a crucial design consideration—not a "fix."&lt;/p&gt;

&lt;p&gt;With the tools we're learning now, the power to design amazing user experiences is at our fingertips. With that power also comes responsibility. As developers, we are responsible for ensuring that the wonderful things we create are accessible to anyone who might use them.&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>a11y</category>
      <category>codenewbie</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
