What I've Coded This Week (Week 3—WWCode '100 Days of Code' Challenge)
Tags: webdev, programming, learning, coding
Published: 2024-02-14 19:44:08

*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).*

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.

## Quick Links
- [React Native—The Case of the Missing Arrows in 'React Native Calendars'](#react-nativethe-case-of-the-disappearing-arrows-in-react-native-calendars)
- [JavaScript—JavaScript30 Project #3: CSS Variables](#javascriptjavascript30-project-3-css-variables)
- [JavaScript—JavaScript30 Project #4: Array Cardio (Day 1)](#javascriptjavascript30-project-4-array-cardio-day-1)
- [Responsive Design—Kevin Powell's 'Conquering Responsive Layouts' (Week 1)](#responsive-designkevin-powells-conquering-responsive-layouts-week-1)

## React Native—The Case of the Missing Arrows in React Native Calendars

In [my last update](https://dev.to/baspin94/what-ive-coded-this-week-week-2-wwcode-100-days-of-code-challenge-657#react-nativepatching-packages), I mentioned that I would be working with the ['React Native Calendars' library](https://wix.github.io/react-native-calendars/) 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 `<Calendar>` 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.

![Comparison of mobile view (with calendar arrows rendered) and web view (without calendar arrows rendered)](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nkb8i92aszkwp4jm9oee.png)

I found a [stale GitHub issue about the missing arrows](https://github.com/wix/react-native-calendars/issues/801) and saw that another user had success unearthing the arrows by modifying the arrow's `height` and `width` within the component's `theme` (the working theory being that, because there was no `height` or `width` explicitly set for the images, they weren't rendering), so I tried this for myself:
```JavaScript
import { View } from 'react-native';
import { Calendar } from 'react-native-calendars';

function CalendarView() {

    return (
        <View>
            <Calendar 
	            theme={{
	                arrowHeight: 50,
	                arrowWidth: 50
	            }}
            />
        </View>
    )
}
```

The result looked oddly blurry.

![Calendar with blurry arrow buttons](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pgug3m81i8zy4bftnhq4.png)

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!):


![Small right arrow which is the default arrow image used in React Native Calendars](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tap2zc7us4i5aua2t4lu.png)

To get around this, I took the [suggestion of another user in the issue thread](https://github.com/wix/react-native-calendars/issues/801#issuecomment-509557261) to create custom `<Arrow>` components, utilizing SVG icons from the [React Native Vector Icons library](https://www.npmjs.com/package/react-native-vector-icons). 

```JavaScript
import { View } from 'react-native';
import { Calendar } from 'react-native-calendars';
import Icon from 'react-native-vector-icons/MaterialIcons'

function CalendarView() {

	const leftArrow = <Icon 
		name="keyboard-arrow-left"
		size={30}
		color='#62BEC1'
	/>
	
	const rightArrow = <Icon
		name="keyboard-arrow-right"
		size={30}
		color='#62BEC1'
	/>

    return (
        <View>
            <Calendar 
	            renderArrow={(direction) => {if (direction == "left") return leftArrow;
								if (direction == "right") return rightArrow;  
                            }}
            />
        </View>
    )
}
```

Unlike PNG files, SVG files can be resized without losing resolution, which we need here. (Check out this [helpful comparison of PNG vs. SVG from Adobe](https://www.adobe.com/creativecloud/file-types/image/comparison/png-vs-svg.html#:~:text=While%20PNGs%20are%20capable%20of,size%20without%20losing%20their%20resolution.) for more info.)

Here's what the calendar looks like now:

![Web view of calendar with arrow vector icons rendered](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dfo4noytxl6e4xm8xi1i.png)

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.

## JavaScript—JavaScript30 Project #3: CSS Variables

The third project in [Wes Bos's JavaScript30 course](https://javascript30.com/) was an intriguing exercise that introduced me to a concept I was as yet unfamiliar with: [CSS variables](https://developer.mozilla.org/en-US/docs/Web/CSS/Using_CSS_custom_properties), also known as custom properties. 

![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](https://res.cloudinary.com/dgoxoljsj/image/upload/v1707869783/CleanShot_2024-02-13_at_16.10.00_ipvetc.gif)

These handy variables allow you to update multiple properties simultaneously with JavaScript. Unlike the variables in the [Sass library](https://sass-lang.com/) 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.

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.
```css
.hl {
    color: #ffc600;
}

img {
    background: #ffc600;
}
```
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.
```javascript
const text = document.querySelector('.hl')
const image = document.querySelector('img')

const input = document.getElementById('base')
input.addEventListener("input", (e) => handleColor(e))

function handleColor(e) {
    text.style.color = e.target.value
    image.style.background = e.target.value
}
```
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.

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 `var(--variable)`.
```css
  :root {
    --color: #ffc600;
  }

  .hl {
    color: var(--color);
  }

  img {
    padding: 10px;
    background: var(--color);
  }
```
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.
```javascript
const input = document.getElementById('base')
input.addEventListener("input", (e) => handleColor(e))

function handleColor(e) {
    document.body.style.setProperty('--color', e.target.value)
}
```
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 `id` 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.

```javascript
function handleChange(e) {
    id = e.target.id
    value = e.target.value
    if (id === "base") {
        document.body.style.setProperty(`--${id}`, value)
    } else {
        document.body.style.setProperty(`--${id}`, `${value}px`)
    }
}
```
You can check out the [code and finished product for Project #3 on GitHub](https://github.com/baspin94/JavaScript30/tree/master/03%20-%20CSS%20Variables).

### A Note on the 'Input' Event
I used the `input` event when setting my event listeners. I was initially confused by Wes's approach of adding separate event listeners for `mousemove` and `change` events on the page inputs. Looking closely at the [MDN reference for "input"](https://developer.mozilla.org/en-US/docs/Web/API/Element/input_event), though, I realized that the `input` 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.
## JavaScript—JavaScript30 Project #4: Array Cardio (Day 1)
This project was, as promised by the title, a great workout and refresher on the various array methods, including `.filter()`, `.map()`, `.sort()`, and `.reduce()`.

These exercises were an excellent opportunity for me to go back and review what gets returned by each of these methods.
- `.filter()`: returns a shallow copy of the original array containing the filtered values.
- `.map()`: returns a new array containing the 'mapped' elements of the original array.
- `.sort()`: returns the **same** array, sorted in place.
- `.reduce()`: 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 `reduce` exercises here returned an integer value; the other one an object with the tallied appearances of each 'key' element in the original array).

The only one of these methods I haven't used somewhere before was `reduce()`, 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.

Here is how I would have written out Question 4 () before learning about `.reduce()`:
```javascript
// Array.prototype.reduce()
// 4. How many years did all the inventors live all together?
function totalLifespan(inventorArray) {
    let totalLifespan = 0
    for (let inventor of inventorArray) {
        totalLifespan += (inventor.passed - inventor.year)
    }
    return totalLifespan
}
const totalYears = totalLifespan(inventors)
console.log("Question 4:", totalYears)
```
With `.reduce()`, I was able to streamline this code quite a bit! I created a callback function, `lifespan`, 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.
```javascript
function lifespan(total, inventor){
    return total + (inventor.passed - inventor.year)
}
const totalYears = inventors.reduce(lifespan, 0)
console.log("Question 4:", totalYears)
```
You could even write that callback inline using an arrow function.
```javascript
const totalYears = inventors.reduce((total, inventor) => {
    return total + (inventor.passed - inventor.year)
}, 0)
console.log("Question 4:", totalYears)
```
You can check out the [code and finished product for Project #4 on GitHub](https://github.com/baspin94/JavaScript30/tree/master/04%20-%20Array%20Cardio%20Day%201).

## Responsive Design—Kevin Powell's 'Conquering Responsive Layouts' (Week 1)
This past week, I started working through [Kevin Powell's 'Conquering Responsive Layouts' course](https://courses.kevinpowell.co/conquering-responsive-layouts). 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. [Kevin's YouTube channel](https://www.youtube.com/@KevinPowell) 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.

![GIF demonstrating a responsive header created as part of Week 1 project. The heading text reads "Responsive Layouts Don't Need to Be A Struggle". Underneath some placeholder text is a 'I Want to Learn' button.](https://res.cloudinary.com/dgoxoljsj/image/upload/v1707876452/CleanShot_2024-02-13_at_18.06.26_wureai.gif)

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 (['5 simple tips to making responsive layouts the easy way'](https://lnkd.in/gTUxE4gA)) that I watched last year while taking some initial steps to make my ['Accessible Parks' app](https://parks.baspin.dev/) more responsive: HTML *is*, 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: 

- **Fixed widths:** Setting the `width` 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 `width` with percentages instead will remove that guesswork. 
	- `max-width`: To account for larger screens where you don't want your layout to stretch too far, you can set the `max-width` property using pixels. 
		- 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: [Readability: The Optimal Line Length](https://baymard.com/blog/line-length-readability)

- **Heights:** It's better to avoid assigning a `height` property and let the `width` 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 `padding`.

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

## Looking Ahead

That's a wrap for this week!

Here's what I'll be working on until my next post:
- Week 2 of [Kevin Powell's Responsive Design Course](https://courses.kevinpowell.co/conquering-responsive-layouts)
- Working through part of Colt Steele's [JavaScript Pro: Mastering Advanced Concepts and Techniques](https://www.udemy.com/course/pro-javascript/)
- Another project from [JavaScript30](https://javascript30.com/)
- More React Native Calendars (styling and customization)