DEV Community

Cover image for React Pre-Requisite: JS Must Know Concepts Before Learning React
shahabbukhari
shahabbukhari

Posted on

React Pre-Requisite: JS Must Know Concepts Before Learning React

Many of you learned javascript and wanted to learn to react to the most popular library for javascript in the market as well as in the community right now. and according to the Stack Overflows 2021 survey React is the most wanted and desired library by one in four developers.

Javascript Meme

Must-Know Javascript Concepts:

React makes it painless to create interactive UIs user interface-based components. But. But. Before building a complex skyscraper with the help of React we should dig deeper in the daunting caves of javascript to build a foundation to build these complex web apps.
As a famous saying is “don’t reinvent the wheel” There's certainly truth there, but I think it's a bit dangerous if taken too literally for me the reinvented version of the quote will be “Don't Reinvent The Wheel Unless You Plan on Learning More About Wheels”.
Before getting emersed in the world of reacting there are some pre-requisites or core concepts and different styles of programming in javascript and you should have a better understanding of it before learning to react.

Let and Const:

With ES6 javascript surprise us with the new way to declare variables in javascript with let
and const in contrast to the old way of declaring a variable with var introducing let and cons was issues developers had to face with scoping and hoisting in var.

Let:

let variables are scoped to the immediate enclosing block denoted by {} (hence the block scope). Variables declared with let and const are also hoisted but, unlike var, are not initialized with a default value. An exception will be thrown if a variable declared with let or const is read before it is initialized.

// Hoisting
console.log(num); // Throws ReferenceError exception as the variable value is uninitialized
let num = 6; // Initialization
// Scope
var name = "Shahab"
console.log(name) // Shahab

function myName() {
    var name = "Ali"
    console.log(name) // Ali
}
myName()
console.log(name) // Shahab
Enter fullscreen mode Exit fullscreen mode

Const:

const declarations share some similarities with let declarations. the only difference is the value assigned with const remains the same within its scope.

const name = "Shahab";
name = "Ali";// error: Assignment to constant variable.
Enter fullscreen mode Exit fullscreen mode

Note: Every const declaration, therefore, must be initialized at the time of declaration.

For More In-depth analysis of scopes, hoisting and Coercion check my other article.

Template Literals:

Template literal provides an easy way to insert multiple variables and expressions into strings allowing for multi-line strings, for string interpolation.

Template literals are enclosed by backtick () characters instead of double (") or single quotes('). And ${...} as a string place holder to insert variables or expressions in it.

let firstName = "Shahab"
let lastName = "Bukhari"
console.log(`My name is ${firstName} ${lastName}`);
// My name is Shahab Bukhari
Enter fullscreen mode Exit fullscreen mode

Destructing:

ES6 comes with Destructuring assignment a new way of unpacking desired values from an array of properties from an object and assigning them into distinct variables.

// Array
let topStudents = ["Jhon Doe", "Alan Turing", "Einstein", "Hawking", "Newton"];
let [firstSTD, secondSTD, thirdSTD] = topStudents
console.log(firstSTD, secondSTD, thirdSTD); 
//Jhon Doe, Alan, Turing Einstein

// Object
let myPhone = {
    model: "Iphone 13 Pro Max",
    year: 2021,
    camera: "12-megapixel",
    price: 1000
}
let {model, price} = myPhone
console.log(`I have ${model} which cost around ${price}$`);
//i have Iphone 13 Pro Max which cost around 1000$
Enter fullscreen mode Exit fullscreen mode

You can also skip some items in an array. What if you only want first and last student in.

let topStudents = ["Jhon Doe", "Alan Turing", "Einstein", "Hawking", "Newton"];
let [firstSTD ,,,, lastSTD] = topStudents
console.log(firstSTD, lastSTD); // Jhon Doe, Newton
Enter fullscreen mode Exit fullscreen mode

The comma separator is used to skip values in an array. So if you want to skip an item in an array, just use a comma.

Spread Operator:

The Spread Operator is three dots (...) that is used to perform several tasks. The spread operator allows us to quickly copy all or part of an existing array or object into another array or object. As a name suggests it spreads the elements of an array or object in another array or objects.

let oddNum = [1,3,5,7,9]
let evenNum = [2,4,6,8]
let numbers = [...evenNum, ...oddNum].sort()
//[  1, 2, 3, 4, 5, 6, 7, 8, 9 ]
Enter fullscreen mode Exit fullscreen mode

Ok, cool why do we need it. The spread operator helps us deal with the problem of immutability(which we will be covering in the Functional Programming Section extensively).

THIS:

In JavaScript, this keyword refers to an object. Which object depends on how this is being invoked (used or called).

For the sake of simplicity, let's discuss the two main Cases.

  1. When used in a normal function:

    When this is used in a normal function it refers to the window object or global in node.

    function hello() {
        let a = 'hello'
        console.log(this)
    }
    hello()
    // Window {window: Window, self: Window, document: document, name: '', location: Location, …}
    
  2. When used as a method in an object:

    When this is used as a method in an object it refers to the object from which its executing.

    const ohh = {
        name: "shahab",
        say: function() {
            console.log(this)
        }
    }
    ohh.say()
    // {name: 'shahab', say: ƒ}
    

Arrow Functions:

Arrow functions are a useful new feature of ES6 An arrow function expression is a compact alternative to a traditional function expression, but arrow functions are limited and can't be used in all situations.

Let's write a function that returns a square of any number.

// Old Way
const square = function(a) {
    return a * a
}
// Modern Way
const square = (a) => {
    return a * a;
}
console.log(square(2)); // 4
Enter fullscreen mode Exit fullscreen mode

It can get shorter. If a function is only accepting one argument then you can remove the ( parenthesis and if the function has only one statement you can also remove the { braces and the function returns the statement by default. Now, let's rewrite the function.

const square = a => a * a;
Enter fullscreen mode Exit fullscreen mode

Note: Remember I said, “Arrow Functions are limited and can't be used in all situations.” one of the places where you should not use the arrow function is with this keyword. And can cause difficult to track errors. the reason behind this is Arrow functions do not bind their own this
, instead, they inherit the one from the parent scope
.
Let's take an example where the arrow function is used as a method in an object.

const myObject = {
  myMethod: () => {
    console.log(this);
  }
};
myObject.myMethod() // window or global object
Enter fullscreen mode Exit fullscreen mode

Weird! remember as we discussed arrow functions do not bind their own this they inherit it from the parent which in this case is the window or global object.

Modules:

When you are working in react or any complex type of application you split your code into multiple files called modules or components in react.js.

A Module is just a reusable code/file that performs a certain task that we have isolated from the rest of our code for managing the complexity of the application. Before ES6 the only way to work with modular javascript was external libraries but now things have been changed ES6 itself supports modules.

  • Export: export can be used to make something visible outside the module/file.

    // 📁 Info.js
    // In-Line Individually
    export const name = "Shahab";
    export const course = "Computer Science";
    // All at once at bottom
    export {name, course}
    

    If you are only exporting one variable you can use export default.

    // 📁 Info.js
    let fullName = `${name} Bukhari`
    export default fullName // only one variable can be default exported
    

    both export and export default can be used in the same file.

  • Import: import can be used to import exported variables from a module/file to use in a current file.

    // 📁 main.js
    import { name, course } from './Info.js'
    import fullName from './Info.js'
    

    Multiple modules exported with export keyword can be accessed through object destructing and any module exported with export default keyword can be imported as a single variable. and now you can use these variables in your current file/module.

    // 📁 main.js
    console.log(name, course) // Shahab, Computer Science
    console.log(fullName) // Shahab Bukhari
    

Basic of Functional Programming:

Functional Programming is a programming paradigm or you can say it's a way of thinking in which we try to build programs by composing pure functions(We will get back to pure functions). Understanding the basic concepts of functional programming is a valuable skill for any react developer.

In javascript functions are first-class citizens which means you can store functions in variables, pass them to other functions as arguments, and return them from other functions as values. you declare a function with var, let, or const keyword as you declare any other variable.

Functional programming is a part of a larger programming paradigm: declarative programming. Declarative programming is a style of programming where applications are structured in a way that prioritizes describing what should happen over defining how it should happen.

Now let's discuss some core concepts of functional programming.

Immutability:

In a literal sense, Immutability means unchangeable. In a paradigm of functional programming, after initializing an object we do not change its values or its state. Think of immutability as “save as” because you know it returns a newly changed object while traditional in-place mutation would be like “save” which means updating the original and letting go of an earlier state.

Immutability gives stricter control over your data immediately making your code safer and more predictable.

before this let's understand the problem of why we need immutability. There are two types of data in javascript primitive (pass by value) and non-primitive(pass by reference).
Javascript has 5 data types that are passed by valueBooleannullundefinedString, and Number. We’ll call these primitive types.

Javascript has 3 data types that are passed by referenceArrayFunction, and Object. These are all technically Objects, so we’ll refer to them collectively as Objects.

Primitive types are easier to make immutable because when you assign a primitive data type to another variable it stores its value.

let myName = "shahab"
let newName = myName
newName = "shahab bukhari"

console.log(myName) // shahab
console.log(newName) // shahab bukhari
Enter fullscreen mode Exit fullscreen mode

but in terms of non-primitive type data is passed as a reference that's because when variables that are assigned a non-primitive value are given a reference to that value. That reference points to the object’s location in memory. The variables don’t actually contain the value.

let even1to10 = [2,4,6,8,10]
let even1to20 = even1to10
even1to20.push(12)
even1to20.push(14)
even1to20.push(16)
even1to20.push(18)
even1to20.push(20)

console.log(even1to10) // [2,4,6,8,10,12,14,16,18,20]
console.log(even1to20) // [2,4,6,8,10,12,14,16,18,20]
Enter fullscreen mode Exit fullscreen mode

Both of the arrays have the same values. because array even1to20 store the reference to the same location array even1to10 pointing and save the changes on that. That's the classic example of why immutability is important.

luckily we can solve this issue with the spread operator.

let even1to10 = [2,4,6,8,10]
let even1to20 = [...even1to10]
even1to20.push(12)
even1to20.push(14)
even1to20.push(16)
even1to20.push(18)
even1to20.push(20)

console.log(even1to10) // [2,4,6,8,10]
console.log(even1to20) // [2,4,6,8,10,12,14,16,18,20]
Enter fullscreen mode Exit fullscreen mode

That's how we store the values/state of an object/array in a new object/array and then modify it to ensure immutability.

Higher-Order Functions:

Higher-order functions are functions that can manipulate other functions. They can
take functions as arguments, return functions, or both.
Some of the built-in higher-order functions in javascript are. Array.map, Array.filter, and Array.reduce all take functions as arguments.

function calculate(operation, initialValue, numbers) {
  let total = initialValue;
  for (const number of numbers) {
    total = operation(total, number);
  }
  return total;
}
function sum(n1, n2) {
  return n1 + n2;
}
function multiply(n1, n2) {
  return n1 * n2;
}
calculate(sum, 0, [1, 2, 4]);      // 7
calculate(multiply, 1, [1, 2, 4]); // 8
Enter fullscreen mode Exit fullscreen mode

Here calculate(operation, initialValue, numbers) is a higher-order function because it accepts a function as the first argument.

calculate(operation, initialValue, numbers) accepts the first argument a function that describes the operation, the second argument is the initial value, and finally, the third argument is the array of numbers. and then returns the results.

Pure Functions:

A pure function is a function that returns a value that is computed based on its argu‐
ments. Pure functions take at least one argument and always return a value or
another function. They do not cause side effects, set global variables, or change any‐
the thing about the application state. They treat their arguments as immutable data.

A function is only pure if, given the same input, it will always produce the same output. When testing a pure function, you control the arguments, and thus you can estimate the outcome.

function highpass (cutoff, value) { 
    return value >= cutoff
};

highpass(5, 123); // true
highpass(5, 1);   // false
highpass(5, 3);   // false
highpass(5, 6);   // true
Enter fullscreen mode Exit fullscreen mode

Recursion:

Recursion happens when a function calls itself. Code using recursion is usually shorter and more elegant. Sequence generation is cleaner with recursion than with iteration.

There are two components of recursion.

  1. **Recursive Case:** where function calls itself with different arguments if the arguments are the same then it will get stuck in an infinite state. y
  2. Base Case: The last component of a useful recursive function is the base case. The base case is a condition in which a function can return the result without another call to itself

The classic example of recursion where recursion is the best solution: is the Fibonacci sequence.

function Fibonacci(num) {
    if(num <= 1) return num
    return Fibonacci(num-2) + Fibonacci(num-1)
}
console.log(Fibonacci(8)) // 21
Enter fullscreen mode Exit fullscreen mode

Congratulations🥳🥳:

Thanks for reading if you stick till the end and I hope this helped you understand core concepts of javascript which will 100% help you learn react more effectively. If not, try reading it again, and again… until you reach your base case!
For more articles like this you can follow me on dev.to and connect with me on LinkedIn:

Top comments (2)

Collapse
 
afaqaafi profile image
Muhammad Afaq

Awesome! how simply you explained the basics.

Collapse
 
jonrandy profile image
Jon Randy 🎖️

React is the most wanted and desired library by one in four developers.

So, it isn't the most wanted and desired library for 3 in 4 developers? 😉