JS Clean Code — Learning on the job
Published: 2021-04-11 14:09:05

In this post, I've compiled a few tidbits that have helped make my React / JavaScript projects that tiny bit more readable.

Looking forward to discuss, iterate, and improve !

# prerequisites

- optional chaining
- short circuiting
- higher order functions
- es6
- react.js
- styled-components || emotion

# short circuiting to keep things clean

```jsx
// assume 'data' here is an array of objects

const mapValues = 
  data
	? data.map(({ value }) => value) 
	: []

// --------------
// cleaning up ✨
// --------------

const mapValuesCleanedUp = 
  (data || []).map(({ value }) => value)
```

The advantage with this pattern is that it can avoid nesting the ternary operators which can be hard to read. 

If we need to pass another set of data we can do so with ease. For example : `(data || otherData || []).map(...)`. This same change with the ternary operator would result in nesting. For example :

```jsx
const nestedTernary =
  data 
    ? data.map(...)
    : otherData 
      ? otherData.map(...)
      : []
```

**Note :** Short circuiting can be a cause for some pretty counterintuitive bugs. I would recommend going through [this](https://blog.bitsrc.io/the-ultimate-guide-to-the-es2020-nullish-coalescing-operator-231d2b64dfde) article to learn more about it (and a little something something about ES2020).

# arrays to keep things DRY

```jsx
const isValidZipCode = 
  (value) => value.length === 5 || value.length === 10

// --------------
// cleaning up ✨
// --------------

const isValidZipCodeCleanedUp = 
  (value) => [5,10].includes(value.length)
```

With this trick we don't have to repeat the `value.length` bit, and if the requirements grow beyond just `5` and `10` the array can be extended like so: `[5,10,6].includes(value.length)`.

# the good ol' IIFE for consistency

```jsx
// formatting variable data
// in this ex : the 'data' object
// contains one property 'cities'
// and two properties for getting states, i.e.
// 'statesData' and 'allStates'

const formatLocaleData = (data = {}) => {
	const { statesData, allStates, cities = [] } = data

	const getFormattedStates = () => { // <--
		if (statesData) return statesData.map(mapOneWay)
		if (allStates) return allStates.map(mapAnotherWay)
		return []
    }
		
	return {
		cities, // <-- 
		states: getFormattedStates(), // <-- 
	}
}

// --------------
// cleaning up ✨
// --------------

const formatLocaleDataCleanedUp = (data = {}) => {
	const { statesData, allStates, cities = [] } = data

	const states = (() => { // <--
		if (statesData) return statesData.map(mapOneWay)
		if (allStates) return allStates.map(mapAnotherWay)
		return []
    })()
		
	return {
		cities,  // <-- 
		states,  // <--
	}
}
```

The entire idea for me in this example was to keep the `return` object consistent by getting rid of the `getFormattedStates()`. 

The `allStates` and `statesData` are mapped separately (for the same result) so that my react component can consume it.

After cleaning it up, the IIFE maps data and assigns it to the `states` variable in one go.

# destructuring props for easier fallbacks

```jsx
const MyComponent = ({ data }) => {
	const fallback = "loading..."

	return (
		<div>
			<h1>{data?.header || fallback}</h1>
			<p>{data?.summary || fallback}</p>
		</div>
	)
}

// --------------
// cleaning up ✨
// --------------

const MyComponentCleanedUp = ({ data = {} }) => {
	const fallback = "loading..."
	const { header = fallback, summary = fallback } = data

	return (
		<div>
			<h1>{header}</h1>
			<p>{summary}</p>
		</div>
	)
}
```

I was often using the short circuiting pattern like :  `{data.header || "fallback"}` in my react components.

However, if you need to access numerous properties it really helps to have all the fallback values in one place rather than multiple `this || that` conditions in different places. 

# better theming in styled-components

```jsx
import { themeGet } from '@styled-system/theme-get'
import styled from 'styled-components'

const Card = styled.div`
	...

	border-width: ${({ theme }) => 
		theme.borderWidths.small 
			? theme.borderWidths.small 
			: "2px"
	};

	...
`

// --------------
// cleaning up ✨
// --------------

const CardCleanedUp = styled.div`
	...

	border-width: ${themeGet('borderWidths.small', '2px')}

	...
`
```

As you can see, the `themeGet` utility makes things super concise. It was developed as part of the `styled-system` library, but it can be installed and used individually.

It's super simple to use. The `themeGet` function's first argument is the property you want to access and the second arguement is the fallaback .

This is by no means only limited to `styled-components` you can also use it with other CSS-in-JS solutions like `emotion`.

# sane styled components with the CSS prop

```jsx

const DivRelative = styled.div`
	position: relative;
`

const MyComponent = () => (
	<DivRelative>
		"..."
	</DivRelative>
)

// -------------
// cleaning up ✨
// -------------

const MyComponentCleanedUp = () => ( 
	<div css="position: relative;">
	 "..."
  </div>
)
```

On large projects, I found that I often had to create styled components with super random names that had only one line of css (like `<DivRelative />`) above. 

I'd waste precious time thinking of a component name that made an inkling of sense.

The css prop was the definitive answer to this problem !

**Note :** To use the css prop you need include the [babel-styled-components](https://styled-components.com/docs/tooling#babel-plugin) plugin in your babel configuration.

# conclusion

Above all else, I think one of the most important things is to keep things as consistent as possible. It's easy to predict how things work when there is consistency (especially in monolithic setups).  

When adopting new patterns it's imperative that everyone on your team is onboard with the idea and that it actually contributes improved readability. That goes for adopting the above snippets too.

I've often found myself reaching for patterns because it made me feel like a boss but didn't really contribute anything substantial to readability. I once named a component `<LobotomizedOwl />` for example 🤦‍♂️. But I did change it to better name like `<MarginProvider />`. Learn from my mistakes and don't do this !

Which brings me to another topic, naming things.

Naming things is also important in projects. It can cause a lot of confusion when things are not named properly.

For example, it's okay to have longer variable / function names if it clarifies the context for future devs. In this light, something like : `getHumanReadableDatesForSelectElement()` is totally fine. Maybe in this hypothetical project there's 10 different requirements for dates. In this case descriptive variable names could reduce the WTFs per minute.

And of course, it's worth mentioning that comments can and should be used to clarify things. Sometimes code is forced to be complex and in those cases comments can help everyone. Especially junior devs. 

Here's a [great talk](https://www.youtube.com/watch?v=yhF7OmuIILc) by Sara Drasner on 'The Art of Commenting'.

As much as I'm about 'aesthetically pleasing' code, which longer variable names might not be. I'm also inspired by a common saying in the design community :

> ***"Form follows function"***

---