Essential JavaScript features for React

The landscape of modern JavaScript has significantly changed since the release of ES6. Most of the applications built using JavaScript or any of it’s frameworks, have chunks of code which seem too terse to even make sense of it.
For example, consider this piece of code below:
let apple = {color: 'red'};
let {color} = apple;
console.log(color); // red
The above code is an example of object destructuring. It might be difficult for few of us to comprehend what the 2nd line of code signifies and how is it even working.
Hence, comes the need for this article.
In this article, I attempt to highlight the most used or essential features of ES6 that would be helpful when going through the codebase of a react application or even while building one of your own.
Below listed, are few of the most common features of ES6 used often in a React application.
Let / Const
A lot of modern JS code makes liberal use of let
and const
keywords which are used for variable declaration.
Essentially, let
and const
introduce block level scoping in our code.
Check out the example below to see how let
and var
differ in usage.
var x = 1
let y = 2if (x === 1) {
var x = 100
let y = 200
console.log(x) // output: 100
console.log(y) // output: 200
}console.log(x) // output: 100
console.log(y) // output: 2
When using const
to declare a variable, it can maintain a constant value.
const pi = 3.141593
pi = 5.6 // this will throw an error
Arrow functions
Arrow functions have a more succinct syntax compared to function expressions.
// Pre-ES6 way
function sayHello() {
console.log("Hello World..!");
}// The ES6 way
var sayHello = () => {
console.log("Hello World..!");
}
In React and also while writing plain JS code, using arrow functions make your code more terse and prevents this
bugs as they do not re-bind this
.
What is this
again .. you ask?
Well, this
is a binding that is made when a function is invoked, and what it references is determined entirely by the call-site (i.e. how the function is called).
And.. what exactly does this
reference to?
The this
binding points to various objects and it all depends on the call-site of the function invocation.
There are 4 rules that can be applied to the call-site of a function.
- Called with
new
? Use the newly constructed object. - Called with
call
orapply
(orbind
)? Use the specified object. - Called with a context object owning the call? Use that context object.
- Default:
undefined
instrict mode
, global object otherwise.
For more info, checkout the link below. It provides the most lucid explanation on this
.
array.map() method
The map()
method creates a new array with the results of calling a provided function for each array element.
Particularly, useful in creating a list in a react application. Example:
const colors = ["red", "green", "blue"];
const items = colors.map(color => `<li>${color}</li>`);
console.log(items);
Object destructuring
Coming back to the code we saw earlier at the start of this article.
let apple = {color: 'red', quantity: 10, fresh: true};let {color, quantity} = apple;
console.log(color); // red;
console.log(quantity); // 10
Rewriting the above code without object destructuring.
let apple = {color: 'red', quantity: 10, fresh: true};let color = apple.color;
let quantity = apple.quantity;console.log(color); // red
console.log(quantity) // 10
After comparing both the codes, you may concur that the first block of code is much more legible and avoids the redundancy of writing apple.somePropertyName
over and over again.
The curly brackets on the left of the equals sign do not represent a block or an object. It is the new destructuring syntax.
Essentially, the first block of code says, give me a variable called color
and a variable called quantity
, and take it from the apple
object. We’re taking the color
and the quantity
property and putting them into two new variables that will be scoped to the parent block.
Spread operators
Another widely used ES6 feature is ...
aka the spread operator.
To understand it better lets look at an example.
let mid = [3, 4];
let arr = [1, 2, mid, 5, 6];console.log(arr); // [1, 2, [3, 4], 5, 6]
In the above code block, we are not yet using the spread operators and as we can see the result is the mid
array being inserted into the middle of the arr
array as an array within an array.
But what if we want only a single array and not a nested one?
We can use the spread operator. ...
allows the elements of our array to expand.
let mid = [3, 4];
var arr = [1, 2, ...mid, 5, 6];console.log(arr); // [1, 2, 3, 4, 5, 6]
As you can see, when we create the arr
array and use the spread operator on the mid
array, instead of just being inserted, the mid
array expands. Each element of the mid
array is inserted into the arr
array. Resulting, in a single array.
ES6 classes
The class
syntax in JavaScript was introduced in ES6 and it does not attempt to introduce a new inheritance model in JavaScript.
JavaScript still follows the prototype-based inheritance model.
The ES6 classes, basically just add syntactical sugar to the already existing model of constructor functions.
For example:
// class definition
class Person{
constructor(name){
this.name = name;
}
walk(){
console.log(`${this.name} walks`)
}
}// creating a person1 object
const person1 = new Person('Tim')
person1.walk(); // Tim walks
Inheritance
Lets extend the code example in the above section to have a Teacher class which has its own bunch of properties and methods.
// class definition
class Teacher{
teach(){
console.log(`teaches`)
}
}
As Teacher
is essentially a subset of Person
we would like the Teacher
to have the walk()
method of the Person
class. This can be done by inheritance.
To achieve this behavior we will use the extends
keyword.
// rewriting class definition
class Teacher extends Person{
constructor(name, subject){
super(name);
this.subject = subject;
}
teach(){
console.log(`${this.name} teaches ${this.subject}`)
}
}const teacher1 = new Teacher('Han', 'Maths');
teacher1.teach() // Han teaches Maths
teacher1.walk() // Han walks
The Teacher
class is able to extend the walk()
method of the Person
class and also able to use name
property by calling super()
in the constructor function of the teacher class.
Modules
Ideally, a react app is made up of many components. Each component is written in its own file which we can call a module. Inside each module, the classes or objects we define are private by default. To make them public and usable to other modules we need to export
the class or object defined inside a module. The exported class/object can then be used in any other component by importing it using import
keyword.
// Person class in Person.js fileexport class Person{
constructor(name){
this.name = name;
}
walk(){
console.log(`${this.name} walks`)
}
}-------------------------------------------------// Teacher class in Teacher.js fileimport {Person} from './Person'class Teacher extends Person{
constructor(name, subject){
super(name);
this.subject = subject;
}
teach(){
console.log(`${this.name} teaches ${this.subject}`)
}
}
Note the curly braces around Person
import, they are needed when we have named exports i.e. when the class is not a default
export. If a class is default export the curly braces can be dropped.
That’s all folks!
I hope you found the article helpful and with this newly gained knowledge you can start deciphering much of the ES6 code today.
Additionally, you can find more info on ES6 here:
This article is inspired by Mosh Hamedani’s video on JavaScript for React Developers.
For furthering your concepts, do check out this video.
✉️ Subscribe to CodeBurst’s once-weekly Email Blast, 🐦 Follow CodeBurst on Twitter, view 🗺️ The 2018 Web Developer Roadmap, and 🕸️ Learn Full Stack Web Development.