Hey 👋 new reader,
Pluralsight gave me some free

1 month
subscriptions

, get them before
they are gone!

Learn Frontend in 2021

· 13 mins read Edit Post

Frontend engineer changes every year. Different technologies, libraries and techniques. This series is everything you need to know to get up to scratch with Frontend Engineering in 2021.

In this part, we will go over

Modern Arrays, Strings, Objects and Functions

Quickly to recap some common advanced techniques using JavaScript and Typescript types.

Variables

Don’t use var use let or const.

harry = 27

console.log(harry)

var harry = 31

console.log(harry)

What is the output?

> 27
> 31

Why? Because when you use var, the variable declaration is hoisted. The above is the same as this:

var harry = 27

console.log(harry)

harry = 31

console.log(harry)

Use let and const to avoid this.

harry = 27 // ERROR harry is used before it's declared

console.log(harry)

let harry = 31

console.log(harry)

Arrays

// Arrays can have anything inside
const things = [1,2,3,4,'harry',1.2,() => 1, null, undefined, {}]

But to let TypeScript help you out, you should make sure to type the array.

Array types

const things: (number | string)[] = [1,2,3,'harry']

With arrays you can easily access elements using Array Destructure Assignment.

const [first, ...rest] = [1,2,3,4,5]
console.log(first) // 1
console.log(rest) // [2,3,4,5]

You can also do

const [first, second, third] = [1,2,3,4,5]
console.log(first) // 1
console.log(second) // 2
console.log(third) // 3

Strings

Strings are quite straightforward and have loads of classic functions on the type.

"1".padStart(2, '0') // "01"

Simply write a string and press dot to see a list of functions.

Array types

const currency = "£123"
const sign = currency.substring(0, 1) // "£"

But always be on the lookout for translation issues, e.g. if the currency value came from a translated value, then you can’t always be sure that the currency symbol will be on the left. So you have no way of knowing some details about translated strings.

const currency = "123£"
const sign = currency.substring(0, 1) // "1" // not what you initially expect

Finally you should be careful with string interpolation.

All of these are equivalent, but you will have a prettier / auto formatter to choose one of these, so don’t worry about this too much.

'harry'
"harry"
`harry`

But for interpolating things you should always opt for:

const age = 27
const id = '1000'

`${age}{id}` // 271000

Because using + sign coerces the string to a number (if it can).

const age = 27
const id = '1000'
age + id // 1027

Objects

Similar to arrays you can destructure objects too!

const props = { isStarred: true, disabled: false }

const { isStarred } = props

console.log(isStarred) // true

On another note, mutating state is generally considered a bad idea, but for JavaScript it is seen as a bad practice, and will likely be flagged in code reviews as bad code.

const data = { age: 27 }

// ...

data.age = 35

// ...

console.log(data.age) // we have to find all occurrences of data to know what this value is

It is very typical to see the spread operator when modifying objects.

e.g.

const data = { age: 27, name: 'harry'}

const newData = { ...data, age: 35 }

console.log(newData.age) // 35

This seems almost pointless in this example, but it leads us onto a point about functions…

Functions

My first programming language was VB.NET. When you defined a function with arguments you had to state if you wanted to copy the input value ByVal or use a reference to it ByRef. In JavaScript everything (except primitives, e.g. ‘harry’ or 123) is passed ByRef.

const transform = (d) => {
  d.age = 30
}


const data = { age: 27, name: 'harry' }
transform(data);

console.log(data.age); // ???

The answer is 30, as we mutated the data OBJECT when we passed it to transform. To avoid this, I always recommend copying the input object and returning a new copy. e.g.

const transform = (d) => {
  const newData = { ...d } // shallow copies
  newData.age = 30
  return newData
}


const data = { age: 27, name: 'harry' }
const newData = transform(data);

console.log(newData.age); // easy to follow, 30

Or even better, use the spread operator with the averring of keys

const transform = (d) => {
  return { ...d, age: 30 }
}

Which can be condensed to

// Note: js gets confused here because we don't know we are returning an object or starting a function
const transform = (d) => { ...d, age: 30 }

// So wrap in brackets like this, to return an object
const transform = (d) => ({ ...d, age: 30 })

You will also see weird function expressions like this

(() => {
  console.log('I am an IIFE, immediately invoked function expression')
})()

Try to avoid these as you can just write them simply like

const func = () => {
  console.log('I am no longer an IIFE, immediately invoked function expression')
}

(func)()

or

const func = () => {
  console.log('I am no longer an IIFE, immediately invoked function expression')
}

func()

CSS

Everyone has seen the family guy css gif.

SASS

Use sass. It’s great and is better than CSS. The main benefit is that you can have nested selectors, e.g.

.container {
  padding: var(--spacing-multiplier);
  
  h3 { 
    color: red;
  }
}

This transpiles down to

.container {
  padding: var(--spacing-multiplier);
}

.container h3 { 
  color: red;
}

CSS variables

Projects often define CSS variables, such as a spacing multiple. You can access these using the var key word.

.container {
  padding: calc(2 * var(--spacing-multiplier));
}

CSS Modules

This is a great method to write CSS. As they prevent leaky CSS.

e.g.

Panel.tsx
Panel.module.scss
.container {
  padding: calc(2 * var(--spacing-multiplier));
}

// This will effect all h3's on the page that the Panel is included in
h3 {
  color: red;  
}

When you nest and have CSS modules you limit the scope, e.g.

.container {
  padding: calc(2 * var(--spacing-multiplier));


  // This will effect all h3's on the page that are under the CSS module
  // .container
  h3 {
    color: red;  
  }
}
// Panel.tsx
import React from 'react';
import styles from './Panel.module.scss';

export const Panel = ({ title }: { title: string }) => {
  return (
    <div className={styles.container}>
      <h3>{title}</h3>
    </div>
  )
}

If we didn’t use CSS modules here, we could also have another component with a class called ‘container’ and a h3 inside. That CSS we wrote in Panel.module.scss would effect that too! And ‘leak’ into our other components. CSS modules turns all class names into unique strings to prevent this. That way when you use styles.container, it will always be unique.

(in dev mode, localhost you will see a helpful name like the path to your component, but in production it will be random).

Interacting with libraries

To interact with libraries that haven’t been ‘css moduled’, you need to use the global keyword to target those selectors. e.g.

// Panel.tsx
import React from 'react';
import { H3 } from 'a-framework-library';
import styles from './Panel.module.scss';

export const Panel = ({ title }: { title: string }) => {
  return (
    <div className={styles.container}>
      <H3>{title}</H3>
    </div>
  )
}
.container {
  padding: calc(2 * var(--spacing-multiplier));

  // the H3 component applies it's own non-css module'd class names
  // here we are selecting it, and making it more targeted and more specific
  h3:global(.a-framework-h3) {
    color: black;
  }
  
  h3 {
    color: red;
  }
}

Specificty

The more targeted a selector the more specific it is and the higher specificity it has. The highest specificity results in the selector that gets chosen.

.container {
  padding: calc(2 * var(--spacing-multiplier));
  
  // specificity 1
  h3 {
    color: black;
  }

  // specificity 1
  h3 {
    color: red;
  }
}

h3 is red, because if the specificity is tied, the last one is applied.

.container {
  padding: calc(2 * var(--spacing-multiplier));
  
  // specificity 2
  h3:global(.a-framework-h3) {
    color: black;
  }

  // specificity 1
  h3 {
    color: red;
  }
}

h3 is black, because of the higher specificity.

Summary

We have covered SASS/CSS and modern JavaScript Arrays, Strings, Objects and Functions.

Frontend is a broad topic to cover. This is part one of a series in modern frontend development. Stay tuned for part 2.

More reading

Suggested

  • Should you use React.FC for typing React Components — 20 May 2020

    Typescript provides some interfaces to help with writing React components. React.FC is one of those interfaces that is used in a lot of apps to define a functional component. The question you should ask yourself is: should you use React.FC for Typescript react components?

    • react
    • typescript
return home