JavaScript basics to learn ReactJs

So you've decided to learn React? Great! It's one of the most popular open-source JavaScript libraries out there that helps you build component-based interfaces.

If you're just starting with React having a basis of JavaScript foundation to work off of will help you a lot. If you've started learning React a while back but are finding it hard to grasp the concepts, this article will aim to build a solid foundation for your learning path into React.

We will dive into modern JavaScript techniques that will help you in your journey to becoming a React master.

Why I wrote this Article

When I was learning React, I dove right into it without really making sure that I have grasped the basics of JavaScript. After all, React is a JavaScript library. It is built on JavaScript, so it would make sense that having that solid foundation there would make your learning a lot easier.

I had used JavaScript in previous roles, so I wasn't completely new to it but hadn't gone fully into the details of it or refreshed my understanding of it. My most recent role was also very C# focused so a JavaScript refresher was needed. But being the eager beaver that I am, I rushed I dove right into React.

Looking back, this was probably a mistake and I would have been better off doing a quick refresher on modern JavaScript concepts before starting. It would have also made the barrier to entry for React much easier.

So hopefully, if you are reading this article, you're planning or are on your journey with React and this will help you avoid some of the pitfalls that I came across.

Let's get started.

Modern JavaScript Concepts You Should Know Before Learning ReactJS

React, and many other modern JavaScript frameworks and libraries are based on ES6 syntax. So the examples given below are all going to follow the ES6 syntax. You can still use ES5 syntax in your React code if you want to, but ES6 syntax makes things a lot easier.

1. Use Let and Const

Before ES6, the only way to create a variable was by using the var keyword. let and const came out with ES6 as two new ways to create a variable in JavaScript.

These two keywords help keep the code we write more reliable and predictable. Let's dive into the differences between these two keywords a bit more.

What is var?

var keyword is used in the global scope or function scope. Scope refers to the locations these variables are available for use.

Scope of var

When var is used outside of a function, it is then available in the global scope i.e. it is available for use in the whole window. When var is used using inside of a function it is available only within that function.

Let's take a look at the following example:

var message = "Hello World";

function myFunction() {
      var name = "My Name"; 
}

console.log(message); // Hello World
console.log(name); // error: name is not defined

Logging message works because it is globally scoped. Logging name variable fails because it is only accessible within the function called myFunction.

Hoisting of var

Variables created using the var keyword are also susceptible to hoisting in JavaScript. This means that the declarations are moved to the top of their scope before the code is executed. i.e. If we code the following:

console.log(myVariable);
var myVariable = "Hello World";

is interpreted to this:

var myVariable;
console.log(myVariable); //myVariable is undefined
myVariable = "Hello World";

The variable is hoisted to the top of the scope and initialised to undefined before it is used. This can cause some unexpected errors.

Re-declaring var variables

Another thing to consider with var variables is that they can be re-declared and updated.

That means the following is valid:

var message = "Hello World";
var message = "Hello World Again";
message = "I've changed";

This can potentially cause problems if you are unknowingly updating the message variable. For example:

var message = "Hello World";

if(true) {
      var message = "My Name"; 
}

console.log(message); // My Name

If you are not aware that there is already a var variable in the global scope with the same name, then you will overwrite it. And if this message variable is used elsewhere in the code then this could be problematic.

This is where let and const come in.

What is let?

let is now the prefered method of variable declaration in JavaScript because it comes with a few improvements. Let's go over the reasons why that is.

let is block-scoped

let variables are block-scoped. That means that they only live within the set of curly braces they are declared in. For example:

   let myNumber = 4;

   if (myNumber > 3) {
        let myMessage = "Hello world";
        console.log(myMessage);// "Hello world"
    }
   console.log(myMessage) // myMessage is not defined

If the let variable is used outside the code block it is defined then it returns an error.

let can be updated but not re-declared

Similar to var, a let variable can be updated later in the code. However, unlike var, a let variable can only be declared once within its scope. Which makes code more reliable and predictable. Let's look at an example:

let myMessage = "My name is Bob";
myMessage = "Hi Bob";

let greeting = "Welcome to my homepage";
let greeting = "What do you think?"; // error : Identifier 'greeting' has already been declared 

let myNumber = 3;
if(true) {
    let myNumber = 5;
    console.log(myNumber);  // 5
}
console.log(myNumber);  // 3

As you can see from the above if the same let variable is declared in the same scope an error is thrown. However, the same let variable name can be declared in different scopes as they are treated as different variables.

This is why let is better and safer to use than var because it removes the worry of using the same variable name in the same scope.

Hoisting let

Similar to var, a let variable can be hoisted up. However, where var variables are initialised to undefined, let variables are not initialised. This eliminated the reference error we encounter with var.

What is const?

const variables share most of the properties of let variables, with one main exception.

const variables cannot be updated or re-declared

This means that any variable declared with the keyword const remains the same within its scope. It cannot be updated or re-declared. For example, we cannot do the following:

let myMessage = "My name is Bob";
myMessage = "Hi Bob"; // error: Assignment to constant variable. 

let greeting = "Welcome to my homepage";
let greeting = "What do you think?"; // error : Identifier 'greeting' has already been declared

Because of this, every const variable declared must also be initialised at the same time.

One thing to note, however, is that if we are declaring a const object, we cannot update the object but the properties of the object can be updated. Let's take a look:

const customer = {
    name = "James",
    age = 23
}

customer.name = "Robert";

console.log(customer.name); //Robert;

customer = {
   isMember = true,
   membershipNumber = 123
} // error:  Assignment to constant variable.

As you can see, we can update the properties of a const object but we cannot modify or add new properties to it.

Let's sum up the differences

varletconst
Variable Scopefunctionblockblock
Can be re-assignedYesYesNo

So, the recommendation now is to not use var and instead try and use const as default, unless you need to re-assign your variables.

In React, the keyword const is used to declare a functional component. We won't be reassigning the component, therefore it makes sense for it to be a const. For example:

import React from "react";

const Welcome = () => <h1> Welcome to my Component </h1>

export default Welcome;

2. String Templating and concatenation in ES6

Before the release of ES6 we used to have to concatenate string in the following way:

var firstName = "Bob";
var lastName = "Marley";

var message = "Welcome" + " " + firstName + " " + lastName +  " " + "to your homepage.";
console.log(message); // Welcome Bob Marley to your homepage.

This way of concatenating string is very error-prone, as you can imagine, and can be very difficult to read. With ES6 we now have template literals.

Template literals allow us to embed variables directly into our strings, and the compiler will formulate the correct final string. Simply use backticks instead of single or double quotes and use the $ sign along with curly braces to include the variables. Let's take a look at this in practice with the example we used above.

var firstName = "Bob";
var lastName = "Marley";

var message = `Welcome ${firstName} ${lastName} to your homepage.`;
console.log(message); // Welcome Bob Marley to your homepage.

As we can see this is a lot simpler and clearer syntax for concatenating strings. And this syntax fits right into the way of writing React.

3. Importing and exporting modules

React popularised component architecture. Modules/components are built up on top of each other to add functionality and various elements to the page.

JavaScript modules are created and exported to be used in your React application. When building your component hierarchy in React we import only the components we need. So understanding the concepts of importing and exporting in JavaScript is essential to becoming comfortable with React.

Let's look at an example we have used before:

import React from "react";

const Welcome = () => <h1> Welcome to my Component </h1>

export default Welcome;

We have now created a Welcome component that can be used in another component by importing it in.

import React from "react";
import Welcome from "./componenets/Welcome";

const myShop = () => {

     return(
     <div>
         <h1>Today our shop is open</h1>
         <Welcome /> 
     </div>
     )

}

4. Arrow functions

Using arrow functions in your React code will make your code much simpler and easier to read, but also will make you a quicker developer as there are fewer lines of code that you need when using this format when compared to standard functions. Arrow functions can also be used to create React components.

I'm not saying that you can't write React without using arrow functions, in fact, a lot of React code that you come across online will have class components and will also have a lot of standard functions in the codebase. Standard functions are still valid.

But, unlike standard functions, arrow functions do not have their own binding to the this keyword within its definition. This makes it easier to use callbacks in arrow functions and means fewer bugs in code.

//Function expression
const add = function(int1, int2) {
   return int1 + int2;
};

//Arrow function expression
const add = (int1, int2) => int1 + int2;

console.log(add(1, 2)); // 3

5. Destructuring

Introduced in ES6, destructuring will allow you to pull out properties from objects or items in an array into distinct values that can be used in your code.

How to use Destructuring?

Let’s take for example the following object:

const person = {
     name = “Mike”,
     age = 23,
     favouriteColor = “Red” 
}

Before ES6 came along we had to access each property of the object in the following way:

console.log(person.name) // Mike
console.log(person.age) // 23
console.log(person.favouriteColor) // Red

With destructuring, we can access the properties in a more streamlined way.

const { name, age, favouriteColor } = person;

This is the same as accessing each property of the object and assigning it to a variable of the same name.

With destructuring we can now use these new variables without the person. prefix. E.g.

console.log(name) // Mike

How do we use Destructing in React?

In React, before using props that have been passed to your component you can destructure the props object. This is where this feature really shines.

Let’s take a look at the <Car /> component that we create below. We can pass it some props, for example, topSpeed, make, and color. These can then be destructured and used in their own right.

const Car = ({ topSpeed, make, color}) => {

    return (
        <div>
            <h1>{make}</h1>
            <p>Top Speed of: {topSpeed}{/p>
            <p>Color: {color}</p>
        </div>
   ); 

}

This can be taken further if there are objects being passed into the props of your component. You can also destructure the properties of those objects into variables of their own right. The following syntax is used myObject: { property1, property2 }. This will give us access to both myObject and the destructed properties to use within this component.

Let’s take a look at what destructuring looks like in a class component using the example we used above.

class Car extends React.Component {

  render() {
    const {topSpeed, make, color}
  } = this.props;

  return (
        <div>
            <h1>{make}</h1>
            <p>Top Speed of: {topSpeed}{/p>
            <p>Color: {color}</p>
        </div>
   ) ;

}

Once we understand the concept behind destructuring and its benefits we can see how simple it is that can make our code more readable and clear and DRYer, especially when passing down props in React.

6. The spread Operator (…)

The spread operator is a clean way of including all elements of an object or an array. Almost like doing a foreach loop. Let’s take a look:

const nums = [ 1, 2, 3 ];
console.log(...nums); \\ 1 2 3

In the above example, we take the array nums and pass all the values of the array, one by one, into the log function using the spread syntax and the array name.

The benefit of the spread syntax is that it is a shorthand syntax and also it is dynamic. That means that if the length of the array changes then the output would be updated accordingly. No matter how many elements are in the object or array, the log function will still work with the same value.

The spread operator is also very useful when adding new items to an array.

let numArray = [ 1, 2, 3 ];
let new = 4;
numArray = [...numArray, new];
console.log(...numArray); // 1 2 3 4

And also when combining two arrays:

let stringArray = [ 'One', 'two', 'Three' ];
stringArray = [ 'zero', ...stringArray, '4', 'five' ]; // will coming two arrays together. 
console.log(stringArray); // zero One two Three 4 five

let arr1 = [ 1, 2, 3];
let arr2 = [ 4, 5];

arr1 = [ ...arr1, ...arr2 ];
console.log(arr1); // 1 2 3 4 5

One thing to note is that the spread operator will actually create a new arr1 and does not modify the original arr1. This means that the original variables are not mutated.

Spread operators also allow us to clone objects by passing all the key-value pairs from one object to another.

let clone = { ...myObj }

One thing to note is that the spread syntax only does what is called a shallow copy. i.e. it goes only one level deep when copying an array. This is something to remember when trying to copy multi-dimensional arrays.

Overall, there are many benefits of using the spread operator, and these can all be applied to your React application. For example, destructuring pops:

<Modal {...this.props} >

And also for updating state:

this.setState(prevState => {
    return {foo: {...prevState.foo, a: "updated"}};
});

The above will replace this.state.foo with a new object of the same name and properties, except with the value of the a property now set to "updated".

7. Filter

The filter method does what it says on the tin. Use the filter method to return all values in an array excluding ones that meet set criteria. Let's take a look:

const myArray = ['Bob', 'James', 'Sam'];
const nameToRemove = 'Sam';
const result = myArray.filter(nameCheck);

function nameCheck(name) {
    return name !== 'Sam';
}

console.log(result); // Bob James

Simple right? A couple of things to note about the filter method:

  • It creates a new array that only contains elements that have passed the criteria provided.
  • It does not execute if the array being filtered is empty
  • It does not change the original array

8. Map

The map method also creates a new array by iterating through each element in the array and passing it to a provided function. The result is that inserted into a new array.

const myNums = [1, 2, 3];

const result = myNums.map(x => x * 5);

console.log(result); // [5, 10, 15]

If you aren't using the returned array then it is recommended to use forEach instead as this is seen as an anti-pattern. i.e. the code will be doing more work than it needs to.

9. Classes

Classes are a very important concept in React, so having a good handle on this will go a long way in helping you succeed with React.

What are classes?

A class is a template for creating objects. It contains data and code that will work on that data.

This concept is the foundation behind React's component hierarchy. Each component is a class with specific functions and data requirements. Like building blocks of a bigger project.

This is useful because in practice we normally need to create many objects of the same kind. E.g. different types of cars.

By creating classes we can have the building blocks of a car, and simply pass it properties we want the car to have. For example:

class Car {
    constructor(make, color, year, maxSpeed) {
          this.make = make;
          this.color = color;
          this.year = year;
          this.maxSpeed = maxSpeed;
    }
}

Now that the class has been created I can now create a new car out of that class:

let familyCar = new Car("Audi", "Blue", "2018", 120);
let sportsCar = new Car("Ferrari", "Red", "2019", 260);

Methods can then be added to the class and used in the code. For example, let's add a method to our class to change the colour and get a paint job done.

Before the closing bracket of the class and after the closing bracket of the constructor let's add the following code:

getAPaintJob(newColor) {
   this.color = newColor;
}

Now we can call the getAPaintJob function and change the color of our cars to anything we want:

familyCar.getAPaintJob("Black");

console.log(familyCar.color); // Black

React uses this ES6 syntax for classes to build components:

class Car extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
         make: this.props.make,
         color: this.props.color,
         year: this.props.year,
         topSpeed: this.props.topSpeed ,
    };
  }
  render() {
    return (
      <div>
        <h1>My {this.state.make}</h1>
        <p>
          Color: {this.state.color},
          Top Speed: {this.state.topSpeed},
          Year: {this.state.year}.
        </p>
      </div>
    );
  }
}

ReactDOM.render(
  <Car 
  make="Audi" 
  color="Red" 
  year="2018" 
  topSpeed="120"
  />,
  document.getElementById('container')
);

If you are familiar with Object Orientated Programming (OOP) then this concept of classes might be familiar to you.

As you can see classes can be very powerful tools. They help make your code more clean, maintainable and DRY. In my opinion, this is probably one of the most important concepts to grasp when learning React.

Takeway

I hope you found this article helpful. Please do let me know if you have any topics you would like me to write about next.

If you happen to have any tips about learning React yourself, whether you are a beginner or a React Ninja, I'd love to read them in the comments below!

Thanks, and see you in the next article.

Did you find this article valuable?

Support Simplifying Code by becoming a sponsor. Any amount is appreciated!