Beginning development in React can be fun and trivial, however your codebase could quuickly get messy, verbose and unreadable unless some careful toughts are put into the development process. Writing clean (quality) code, many would agree comes with experience and i also belong to that school of thought, however there are simple and often overlooked javascript concepts that i believe if harnessed properly can greatly improve our React code quality. I would list these concepts in no particular order, Lets begin...
Object destructing
To be honest, ive never seen a professional React codebase without this sugar. Its a simple concept that can greatly improve code conciseness. The idea is simple - write variables whose names matches those of the object to be destructured and hold the same value as the name it mirrors.
let {foo, baz} = {foo: 1, bar: "Leave me out", baz: 2}
console.log(foo, baz) // -> 1, 2
This property is used in React mostly to assign variables from a component prop or state, hence avoiding repeated calls to props[dot]this, state[dot]that. I hope you get this idea. 😆
The same also applies for destructuring array, however the index of array elements determines how the operation executes.
Conditional Execution
More often we have logic we want to excute based on some given criteria, using simple if-else statement would suffice, however React developers favor the && operator instead. The code below logs 'congrats' to console if an expression returns 'true'
const isAdult = (age) => age >= 18
isAdult(18) && console.log('Congrats!!!') // 'congrats'
Spread Operators
Often in React codebases you see the spread operator been used to pass props to components, as this is often convinient.
A simple use case for spread operators are passing arbitrary arguments to a function. A simple is how we would calculate the 'mean' from a series of numbers, we could leverage spread operator to make this easy.
const calc_mean = (...series) => series.reduce((sum, n) => sum + n, 0) / series.length;
const mean = calc_mean(2,4,6,8)
console.log(mean) // 5
Using spread operator we can evaluate mean from an arbitrary length of arguments.
Flattening with Array.prototype.reduce()
I chose the word 'flattening' out of recklessness, as i could not come up with something better, do forgive me 😱
However the intent is here is trying to reduce a collection to a single output. Say for instance you have been tasked at your new job to find the percent reviews of a newly shipped product from a given 'customers' sample.
let customers = [
{category: 'happy', count: 1200},
{category: 'sad', count: 204},
{category: 'indifferent', count: 25},
];
// compute total from customers list
let total = customers.reduce((sum, {count}) => sum + count, 0)
// optional: proceed to compute percent for all categories
let customer_reviews = customers.map(customer => {
let percent = customer.count / total * 100
return {...customer, percent: percent.toFixed(2) + '%'}
})
console.log(customer_reviews)
Now we have a list of customers with their average percentage reviews.
Higher Order Functions
This category of higher-order functions discussed here involve those that return a function, as they can greatly result to code conciseness and make abstracting reusable logic a breeze. Say for instance, we want to filter a collection based on another collection
let invite_ids = [ 0, 1, 1, 2, 3, 5, 8, 13, 21, 34]
let friends = [{name: 'sam', id: 1}, {name: 'jon', id: 13}, {name: 'snow', id: 10}]
Fun Fact: The array, invite_ids is actually a fibonacci series 😉
Now we only want those friends whose id can be found in the invite_ids list to attend the party, how do we go about this?
const filter_invites = (ids) => ({id}) => ids.includes(id)
// now we can do this...
let my_invites = friends.filter(filter_invites(invite_ids))
console.log(my_invites) // [{name: 'sam', id: 1}, {name: 'jon', id: 13}]
Now notice how concise and brief we have implemented this logic while still maintaining readability. The function that performs the filtering can even be abstracted for purpose of reusing and/or testing.
Template Literals
Template literals are cool, in-essence they are just like strings, but with more capabilities. Very often, they are used in places where we intend to embed expressions and other code-related logic.
- A simple greeting procedure
function greet(name) {
return `Hello ${name}`
}
greet('mike') // Hello mike
- conditional logic in templates
let friends = ["ola", "tea", "mike"]
let className = `box ${friends.length ? 'show' : 'hidden'}`
console.log(className) // 'box show'
By utilizing template literals we can write inline and more concise conditional expressions.
There are many other concepts to uncover as you write more React code, but i do not intend this post an ultimate authority. Thanks for reading, and i love your feedback.
You can follow me on twitter
Top comments (5)
Hey Emmanuel!
Nice collection of some es6 features.👍
But I’m still searching the focus on React and the tips.
I intentionally excluded actual React code, but trust me if you've worked even a little with React or other JavaScript lib, you can figure out ways to apply some of these concepts in your codebase. Thanks jwe
Yeah, but it’s still just vanilla JS. Has nothing to do with any library.
reduce
belongs to the Fold family and it's a powerful tool for structural transformations. However it is prone to increasing cognitive load when reviewing or simply reading code, see this video, when often a double pass withfilter
andmap
does just as well in performance asreduce
, see this summary, while keeping cognitive load low. Also remember that JS is compiled, and some optimizations may happen to the code.I'd definitely check those out. Thanks for contributing