Skip to main content

3 posts tagged with "javascript"

View All Tags

DOM manipulation in JavaScript

Β· 9 min read

1. Understanding DOM​

  • The Document Object Model (DOM) is a programming interface for web documents.

  • This model allows developers to interact with the document programmatically via scripting languages like JavaScript.

  • When a web page is loaded, the browser parses the HTML and creates the DOM.

  • The DOM represents the document as a tree of nodes, where each node is an object representing a part of the document:

Document Node: Represents the entire document.

Element Nodes: Represent HTML elements like <div>, <p>, <a>, etc.

Text Nodes: Contain the text content within elements.

Attribute Nodes: Represent the attributes of HTML elements (class, id, src etc.).

For example, consider the following HTML:

<!DOCTYPE html>
<html>
<head>
<title>Example with Attributes</title>
</head>
<body>
<h1 class="header" id="main-title" data-info="example">Hello, World!</h1>
<p>This is a paragraph.</p>
</body>
</html>

For this document, the DOM tree would look like this:

Document
β”œβ”€β”€ html
β”‚ β”œβ”€β”€ head
β”‚ β”‚ └── title
β”‚ β”‚ └── "Example with Attributes"
β”‚ └── body
β”‚ β”œβ”€β”€ h1
β”‚ β”‚ β”œβ”€β”€ @class="header"
β”‚ β”‚ β”œβ”€β”€ @id="main-title"
β”‚ β”‚ β”œβ”€β”€ @data-info="example"
β”‚ β”‚ └── "Hello, World!"
β”‚ └── p
β”‚ └── "This is a paragraph."

The DOM plays a central role in web development by enabling developers to create dynamic and interactive web pages.

  • Access and manipulate elements: Developers can use JavaScript to select, modify, and create HTML elements.

  • Handle events: The DOM allows developers to listen for and respond to user events, such as clicks, keypresses, and form submissions.

  • Modify styles: Through the DOM, developers can change the CSS styles of elements dynamically.

2. DOM Manipulation​

2.1. Accessing Elements​

  • To get an element by its ID in JavaScript, you can use the getElementById method.
<div id="title">Hello, World!</div>
// Get the element with the ID 'myElement'
const element = document.getElementById('myElement');

// Log the element to the console
console.log(element);
  • To get elements by their class, we can use the getElementsByClassName method. This method returns a live HTMLCollection of elements with the specified class name.
<div class="myClass">First Element</div>
<div class="myClass">Second Element</div>
<div class="myClass">Third Element</div>
// Get the elements with the class name 'myClass'
const elements = document.getElementsByClassName('myClass');

// Log the elements to the console
console.log(elements);

// Optionally, you can iterate over the elements as well
for (let i = 0; i < elements.length; i++) {
console.log(elements[i])
}
  • To get elements by tag name in the Document Object Model (DOM), we can use the getElementsByTagName method. This method allows you to retrieve a collection of elements that match a specified tag name.
<h1>Hello, World!</h1>
<p>This is a paragraph.</p>
<div>
<p>Another paragraph inside a div.</p>
<p>Second paragraph inside a div.</p>
</div>
// Get all <p> elements in the document
const paragraphs = document.getElementsByTagName("p");

// Loop through and log the text content of each <p> element
for (let i = 0; i < paragraphs.length; i++) {
console.log(paragraphs[i].textContent);
}
  • The querySelector method in JavaScript allows you to select and retrieve the first element that matches a specified CSS selector within the document or within a specific element,
// Select the first <p> element in the document
const firstParagraph = document.querySelector("p");

// Select the element with id="main-title"
const titleElement = document.querySelector("#main-title");

// Select the first element with class="intro"
const introParagraph = document.querySelector(".intro");

// Select the first <p> element inside the <div>
const paragraphInDiv = document.querySelector("div p");
  • The querySelectorAll method in JavaScript allows you to select and retrieve a list (or NodeList) of all elements that match a specified CSS selector within the document or within a specific element. Unlike querySelector, which returns only the first matching element, querySelectorAll returns a NodeList containing all matching elements.

// Select all <p> elements in the document
const paragraphs = document.querySelectorAll("p");

// Log the number of <p> elements found
console.log("Number of <p> elements:", paragraphs.length);

// Select all elements with class="intro"
const introElements = document.querySelectorAll(".intro");

// Select all <li> elements inside the <ul>
const listItems = document.querySelectorAll("ul li");

2.2. Modifying Content​

  • innerHTML allows you to get or set the HTML markup inside an element.
// HTML element
const divElement = document.getElementById("myDiv");

// Get inner HTML content of divElement
const htmlContent = divElement.innerHTML;
console.log("Inner HTML:", htmlContent);

// Set inner HTML content of divElement
divElement.innerHTML = "<p>New content with <strong>bold</strong> text.</p>";
  • textContent allows you to get or set the text content inside an element.
// HTML element
const paragraphElement = document.getElementById("myParagraph");

// Get text content
const textContent = paragraphElement.textContent;
console.log("Text content:", textContent);

// Set text content
paragraphElement.textContent = "Updated text content.";
  • innerText allows you to get or set the visible text content inside an element.
// HTML element
const spanElement = document.getElementById("mySpan");

// Get inner text
// Retrieves the visible text content inside an element, excluding hidden elements or elements with CSS display: none.
const innerText = spanElement.innerText;
console.log("Inner text:", innerText);

// Set inner text
spanElement.innerText = "Updated inner text.";

2.3. Modifying Attributes​

  • Use getAttribute() to get the value of an attribute.
  • Use setAttribute() to set a new value for an attribute.
  • Use removeAttribute() to remove an attribute.
<div class="myClass">First Element</div>
// Get the element with the ID 'myElement'
const element = document.getElementById('myElement');

// Get the value of an attribute
const classValue = element.getAttribute('class');
console.log('Class:', classValue); // Output: Class: myClass

// Set a new value for an attribute
element.setAttribute('class', 'newClass');
console.log('Updated Class:', element.getAttribute('class')); // Output: Updated Class: newClass

// Remove an attribute
element.removeAttribute('class');
console.log(element.hasAttribute('class')); // Output: false

2.4. Creating and Inserting Elements​

  • createElement() method creates a new HTML element.
  • appendChild() method appends a node as the last child of a parent node.
  • insertBefore() method inserts a node before an existing element within a a specified parent node.
  • append() method appends node to the end of a parent node.
  • prepend() method inserts node to the beginning of a parent node.
<body>
<div id="container">
<ul class="todo-list"></ul>
<div>
</body>
const container = document.getElementById('container');
const todolist = document.querySelector('.todo-list');

// Create a new element
const newToDo = document.createElement('li');
newToDo.setAttribute("class", "todo-item")
newToDo.textContent = 'Buy fruits.';

// Append the new element as the last child
todolist.appendChild(newToDo);

// Create another new element
const title = document.createElement('h2');
newToDo.textContent = 'My tasks';

// Insert the title before the list
container.insertBefore(title, todolist);

// Create yet another new element
const lastElement = document.createElement('div');
lastElement.textContent = 'Last Element';

// Append yet another element as the last child
container.append(lastElement);

// Create and prepend a new element
const firstElement = document.createElement('div');
firstElement.textContent = 'First Element';

// Prepend the new element as the first child
container.prepend(firstElement);

2.5. Removing Elements​

  • removeChild() method removes a specified child node from the parent node. The removed child node is returned.

  • remove() method removes the element from the DOM.

<div id="container">
<div id="childElement">Child Element</div>
<div id="anotherChildElement">Another Child Element</div>
</div>
// Get the container element
const container = document.getElementById('container');

// Get the child element to be removed
const childElement = document.getElementById('childElement');

// Remove the child element using removeChild
container.removeChild(childElement);

// Get another child element to be removed
const anotherChildElement = document.getElementById('anotherChildElement');

// Remove the element using remove()
anotherChildElement.remove();

2.6. Modifying Styles​

  • The style property allows to set or get inline styles for an element. This directly modifies the style attribute of the element in the DOM.
<div id="myElement">Hello world!</div>
// Get the element
const element = document.getElementById('myElement');

// Change the background color and font size using the style property
element.style.backgroundColor = 'blue';
element.style.fontSize = '20px';
  • The classList property provides methods to add, remove, and toggle CSS classes on an element. This is a more flexible way to manage an element's classes compared to directly setting the class attribute.
// Get the element
const element = document.getElementById('myElement');

// Add a new class to the element
element.classList.add('newClass');

// Remove an existing class from the element
element.classList.remove('initialClass');

// Toggle a class on the element (add it if it doesn't exist, remove it if it does)
element.classList.toggle('toggledClass');

2.7. Event Handling​

  • The addEventListener() method attaches an event handler to an element. It allows multiple event listeners to be added to a single element for the same event type.
<button id="myButton">Click Me</button>
// Define the event handler function
function handleClick() {
alert('Button was clicked!');
}

// Get the button element
const button = document.getElementById('myButton');

// Add a click event listener
button.addEventListener('click', handleClick);
  • The removeEventListener() method removes an event handler that was added with addEventListener().
button.removeEventListener('click', handleClick);

Conclusion​

Mastering DOM manipulation is crucial for creating dynamic, interactive web pages. The ability to access, modify, and interact with the DOM using JavaScript allows developers to build responsive and engaging user experiences.

  • Understanding the DOM: By understanding the structure and representation of a web document through the DOM, developers can effectively interact with and manipulate web pages.

  • Accessing Elements: Methods like getElementById(), getElementsByClassName(), getElementsByTagName(), querySelector(), and querySelectorAll() enable precise selection of elements within the DOM, facilitating targeted manipulations.

  • Modifying Content and Attributes: Techniques such as using innerHTML, textContent, and innerText for content modification, alongside getAttribute(), setAttribute(), and removeAttribute() for attribute management, provide powerful ways to dynamically change the document's content and properties.

  • Creating and Inserting Elements: Methods like createElement(), appendChild(), insertBefore(), append(), and prepend() allow developers to construct and integrate new elements into the DOM, enabling the dynamic construction of web pages.

  • Removing Elements: Using removeChild() and remove() methods facilitates the removal of elements from the DOM, which is essential for maintaining clean and efficient document structures.

  • Modifying Styles: Direct manipulation of inline styles via the style property and managing classes with classList methods (add(), remove(), toggle()) offer flexible control over the appearance and styling of elements.

  • Event Handling: The ability to attach and remove event listeners using addEventListener() and removeEventListener() empowers developers to create interactive elements that respond to user actions, enhancing the user experience.

By leveraging these DOM manipulation techniques, developers can create rich, interactive web applications that provide a seamless and dynamic user experience. Understanding and utilizing these tools effectively is key to modern web development.

Unveiling the Significance of JS ES6 features

Β· 14 min read
  • In the fast-paced world of web development, staying ahead of the curve is not just an advantage β€” it’s a necessity. Enter ECMAScript 6, or ES6 for short, a game-changer that has redefined the landscape of JavaScript programming.

  • What if you could write JavaScript code that is not only more concise but also more powerful? How would it feel to have a set of features that streamline your workflow, enhance code readability, and unlock new possibilities in your projects? The answer lies in understanding the transformative impact of ES6 on the world’s most widely-used programming language.

  • As we dive into the significance of ES6, we’ll discover how this evolution has not only simplified the developer experience but has also laid the foundation for more robust, expressive, and maintainable code.

  • ES6 introduces a plethora of features that elevate JavaScript development to new heights.

1. let and const​

  • In ECMAScript 2015 (ES6), the let and const keywords were introduced to declare variables, offering improvements over the traditional var keyword.
  • Scope: Variables declared with β€˜let’ and β€˜const’ have block-level scope, meaning they are limited to the block, statement, or expression where β€˜var’ has global level scope.
if (true) {
let x = 10;
const y = 20;
var z = 30;
console.log(x); // Outputs: 10
console.log(y); // Outputs: 20
console.log(z); // Outputs: 30
}


console.log(x); // Outputs: Error: x is not defined
console.log(y); // Outputs: Error: x is not defined
console.log(z); // Outputs: 30
  • Hoisting: Unlike variables declared with var, variables declared with let and const are not hoisted to the top of their scope. They remain in the temporal dead zone until the point of declaration.
console.log(a); // outputs: 20
var a = 20;

console.log(b); // Error: Cannot access 'b' before initialization
let b = 20;

console.log(c); // Error: Cannot access 'c' before initialization
const c = 20;
  • Reassignment: Variables declared with let can be reassigned, allowing for flexibility in updating values where, variables declared with const are constant and cannot be reassigned once a value is assigned.
let p = 30;
p = 40; // Valid

const pi = 3.14;
pi = 3.145; // Error: Assignment to constant variable
  • However, this does not make objects or arrays declared with const immutable; it means the reference to the object or array cannot be changed.
const colors = ['red', 'green', 'blue'];
colors.push('yellow'); // Valid
colors = ['purple']; // Error: Assignment to constant variable
  • Declaration: Variables declared with const must be assigned a value at the time of declaration.
var x; // valid
let y; // valid
const z; // Error: Missing initializer in const declaration

2. Arrow functions​

  • Arrow functions, introduced in ECMAScript 2015 (ES6), provide a concise and more readable syntax for writing functions in JavaScript.
// In ES5
var add = function(x, y) {
return x + y;
};
// ES6 (Arrow Function)
const add = (x, y) {
return x + y;
}
// If the function body is a single expression,
// you can omit the braces {} and the return keyword.
const add = (x, y) => x + y;
  • Arrow functions are more concise compared to traditional function expressions, especially when the function has a simple body.

3. Template literals​

  • Template literals, introduced in ECMAScript 2015 (ES6), provide a more flexible and concise way to create strings in JavaScript. They use backticks (`) instead of single or double quotes and allow for embedded expressions and multiline strings.
  • Embedded expressions: Template literals support the embedding of expressions, including variables, functions, and operations, directly within the string.
// In ES5
var a = 5;
var b = 10;
var result = 'The sum of ' + a + ' and ' + b + ' is ' + (a + b) + '.';

// In ES6 (Template Literal with Embedded Expression)
const a = 5;
const b = 10;
const result = `The sum of ${a} and ${b} is ${a + b}.`;
  • Multiline strings: One of the significant advantages of template literals is their ability to create multiline strings without the need for explicit line breaks or concatenation.
// In ES5
var multilineString = 'This is a long string\n' +
'that spans multiple lines\n' +
'using concatenation.';

// In ES6 (Template Literal)
const multilineString = `This is a long string
that spans multiple lines
using template literals.`;

4. Destructuring assignments​

  • Destructuring is a powerful feature introduced in ECMAScript 2015 (ES6) that allows you to extract values from arrays or properties from objects and assign them to variables in a more concise and expressive way.
  • It simplifies the process of working with complex data structures.
  • Array destructuring
// In ES5
var numbers = [1, 2, 3];
var a = numbers[0];
var b = numbers[1];
var c = numbers[2];

// In ES6
const [a, b, c] = [1, 2, 3];
console.log(a, b, c); // Outputs: 1 2 3
  • Object destructuring - Alias assignment, Nested destructuring
// In ES5
var person = { name: 'John', marks: 85 };
var name = person.name;
var marks = person.marks;

// In ES6
const person = { name: 'John', marks: 85 };
const { name, marks } = person;
console.log(name, marks); // Outputs: John 85

// In ES6 - alias assignment
const person = { name: 'John', marks: 85 };
const { name: studentName, marks: finalMarks } = person;
console.log(studentName, finalMarks); // Outputs: John 85

//In ES6 - Nested destructuring
const user = {
name: 'John',
age: 30,
address: {
city: 'New York',
country: 'USA'
}
};

const { name, age, address: { city, country } } = user;
console.log(name, age, city, country); // Outputs: John 30 New York USA
  • Function Parameter Destructuring
// ES6
function printPerson({ firstName, lastName }) {
console.log(`${firstName} ${lastName}`);
}

const person = { firstName: 'John', lastName: 'Doe' };
printPerson(person); // Outputs: John Doe

5. Default parameters​

  • Default parameters, introduced in ECMAScript 2015 (ES6), allow you to assign default values to function parameters in case the arguments are not provided or are explicitly set to undefined.
// without default values

function add(x, y) {
return x + y;
}
console.log(add()); // outputs NaN
console.log(add(1, 2)); // outputs 3

// let’s see how we handle this issue in ES5 and ES6.

// In ES5
function add(x, y) {
x = x || 0;
y = y || 0;
return x + y;
}

// ES6 (Default Parameters)
function add(x = 0, y = 0) {
return x + y;
}

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

6. The spread and rest operator​

  • The rest and spread operators are two powerful features introduced in ECMAScript 2015 (ES6) that enhance the way we work with arrays and function parameters. Despite having similar syntax (the ellipsis …), they serve different purposes.
  • As the name suggests, the spread operator β€œspreads” the values in an array or a string across one or more arguments. In cases where we require all the elements of an iterable or object to help us achieve a task, we use a spread operator.
// In ES6 - spread operator example 1 with array

const greeting = ['Welcome', 'back', 'John!'];

console.log(greeting); // ['Welcome', 'back', 'John!']
console.log(...greeting); // Welcome back John!

// Note: console.log(...greeting) is equivalent to console.log('Welcome', 'back', 'John!');
// In ES6 - spread operator example 1 with Object

const obj1 = { a : 1, b : 2 };

// add members obj1 to obj3
const obj2 = { ...obj1, c: 3 };
console.log(obj2); // {a: 1, b: 2, c: 3}
  • The rest operator is converse to the spread operator. while the spread operator expands elements of an iterable, the rest operator collects several elements compress them into an array. In functions when we require to pass arguments but were not sure how many we have to pass, the rest parameter makes it easier.
// In ES6 - rest operator example 1
let func = function(...args) {
console.log(args);
}

func(3); // [3]
func(4, 5, 6); // [4, 5, 6]

// In ES6 - rest operator example 2
function func(a, b, ...nums) {
console.log( a + ' ' + b ); // 1 2
// the rest go into titles array
console.log(nums); [3, 4, 5]
}

func(1, 2, 3, 4, 5);

// Note: There must be only one rest operator in javascript functions and
// should always be at the end in the parameter list, else it causes an error.

7. Promises​

  • Promises were introduced in ECMAScript 2015 (ES6) to simplify asynchronous programming and provide a more structured way to handle asynchronous operations. They are especially useful for dealing with asynchronous operations like network requests, file reading, or timeouts.
  • Creating a promise β€” A Promise is created using the Promise constructor, which takes a function called the "executor." The executor function has two parameters, resolve and reject, which are functions provided by the Promise implementation.
  • A Promise can be in one of three states: Pending, Fulfilled, Rejected
  • Pending: The initial state; the promise is neither fulfilled nor rejected.
  • Fulfilled: The operation completed successfully, and the promise has a resulting value.
  • Rejected: The operation failed, and the promise has a reason for the failure.
  • Handling promises β€” To handle the result of a Promise, you can use the .then() method for success and .catch() method for failure. These methods are called on the Promise instance.
// creating a promise
const fetchData = () => {
return new Promise((resolve, reject) => {
// Simulate an asynchronous operation (e.g., fetching data from a server)
setTimeout(() => {
const success = Math.random() > 0.5; // Simulate success or failure randomly

if (success) {
const data = { message: 'Data successfully fetched!' };
resolve(data); // Resolve with the fetched data
} else {
reject(new Error('Failed to fetch data')); // Reject with an error
}
}, 1000); // Simulate a 1-second delay
});
};

// handling promise
fetchData()
.then((result) => {
console.log(result.message);
})
.catch((error) => {
console.error(error.message);
});
  • We define a function fetchData that returns a new Promise.

  • Inside the Promise constructor, we simulate an asynchronous operation using setTimeout. The operation randomly succeeds or fails.

  • If the operation is successful, we call resolve with an object representing the fetched data. If there is an error, we call reject with an Error object.

  • We use the then method to handle the successful result and the catch method to handle errors.

  • promise.all() β€” A utility method that takes an array of Promises and returns a new Promise that is fulfilled with an array of the fulfilled values when all the promises in the array are fulfilled. If any promise in the array is rejected, the resulting Promise is rejected with the reason of the first rejected promise.

const promise1 = Promise.resolve('One');
const promise2 = Promise.resolve('Two');
const promise3 = new Promise((resolve, reject) => {
setTimeout(() => resolve('Three'), 1000);
});

Promise.all([promise1, promise2, promise3])
.then((results) => {
console.log(results); // Outputs: ['One', 'Two', 'Three']
})
.catch((error) => {
console.error(error);
});

  • promise.race() β€” Similar to Promise.all(), but it settles as soon as any of the promises in the array settles, either fulfilled or rejected.
const promise1 = Promise.resolve('Fast');
const promise2 = new Promise((resolve, reject) => {
setTimeout(() => resolve('Slow'), 2000);
});

Promise.race([promise1, promise2])
.then((result) => {
console.log(result); // Outputs: 'Fast'
})
.catch((error) => {
console.error(error);
});

8. Modules​

  • In ECMAScript 2015 (ES6), the module system was introduced to allow developers to organize their code into reusable and maintainable pieces. Before ES6 modules, JavaScript relied on various patterns like immediately-invoked function expressions (IIFE) or the CommonJS pattern for modular development. ES6 modules provide a standardized and native way to work with modules in JavaScript.
  • In ES6, a file becomes a module when it contains at least one import or export statement.
  • export statement is used to specify what values are accessible from a module, and the import statement is used to bring those values into another module.
  • Individual export
// student.js
export const name = "Mary";
export const age = 17;

// main.js
import { name, age } from "./person.js";
console.log(name, age); // outputs: Mary 17


- All at once export
// student.js
const name = "Jesse";
const age = 40;

export {name, age};

// main.js
import { name, age } from "./person.js";
console.log(name, age); // outputs: Mary 17
  • default export β€” A module can have a default export, which is the main export of the module. It is often used when a module represents a single value or function.
// myModule.js

// Default exporting a function
export default function() {
console.log('Default function executed!');
}

// main.js

// Importing the default export
import myDefaultFunction from './myModule';

myDefaultFunction(); // Outputs: Default function executed!

9. Classes​

  • Classes in ECMAScript 2015 (ES6) introduced a more convenient and syntactic way to create constructor functions and work with prototype-based inheritance. JavaScript, being a prototype-based language, lacked a formal class structure prior to ES6.
  • Classes provide a cleaner and more familiar syntax for creating objects and organizing code in an object-oriented manner.
class Animal {
// Constructor method for initializing instances
constructor(name, sound) {
this.name = name;
this.sound = sound;
}

// Method for making the animal make its sound
makeSound() {
console.log(`${this.name} says ${this.sound}`);
}
}

// Creating instances of the class
const dog = new Animal('Dog', 'Woof');
const cat = new Animal('Cat', 'Meow');

// Using class methods
dog.makeSound(); // Outputs: Dog says Woof
cat.makeSound(); // Outputs: Cat says Meow

Classes support inheritance through the extends keyword. This allows a new class to inherit the properties and methods of an existing class.

class Cat extends Animal {
constructor(name, sound, color) {
super(name, sound); // Calls the constructor of the parent class
this.color = color;
}

// unique method for cats
purr() {
console.log(`${this.name} purrs softly.`);
}
}

const kitty = new Cat('Kitty', 'Meow', 'White');
kitty.makeSound(); // Outputs: Kitty says Meow
kitty.purr(); // Outputs: Kitty purrs softly.

10. Symbols​

  • Symbols are a primitive data type introduced in ECMAScript 2015 (ES6) to provide a way to create unique identifiers.
  • Unlike strings or numbers, symbols are guaranteed to be unique, which makes them useful for scenarios where you need to create property keys that won’t clash with other properties.
// creating symbol
const mySymbol = Symbol();
console.log(typeof mySymbol); // Outputs: symbol

Symbols are guaranteed to be unique, even if they have the same description. The description is a human-readable string that can be used for debugging but does not affect the uniqueness of the symbol.

const symbol1 = Symbol('apple');
const symbol2 = Symbol('apple');

console.log(symbol1 === symbol2); // Outputs: false

// Symbols are often used to create non-enumerable properties on objects,
// helping prevent unintentional name collisions.

const myObject = {
[Symbol('key')]: 'value',
};

for (const key in myObject) {
console.log(key); // No output, as the symbol property is non-enumerable
}

console.log(Object.keys(myObject)); // Outputs: []

conclusion​

From the simplicity of arrow functions to the modularity of ES6 modules, and the flexibility of template literals, ES6 has revolutionized the way developers write and structure their code. The introduction of let and const for variable declarations, destructuring for concise data extraction, and the powerful features of Promises for asynchronous operations have all contributed to a more robust and developer-friendly JavaScript.

ES6 not only addressed common pain points in JavaScript but also paved the way for a more modern and scalable approach to building applications. With advancements like the spread and rest operators, default parameters, and the introduction of classes for object-oriented programming, ES6 has empowered developers to create cleaner, more maintainable code.

In conclusion, ES6 has not only elevated the capabilities of JavaScript but has also redefined the developer experience, making it more enjoyable and productive.

React JS

Β· 12 min read

React is a JavaScript library primarily used for building user interfaces in single-page applications. While it's often integrated with tools like Webpack for bundling JavaScript and CSS files, React itself does not directly incorporate Webpack. Despite its nature as a library rather than a full framework or programming language, React remains instrumental in modern web development.

React offers various extensions for entire application architectural support, such as Flux and React Native, beyond mere UI.

Why React?​

  • Declarative Nature: React's declarative approach allows developers to describe the desired UI state, and React handles the rendering efficiently. This simplifies the development process by abstracting away the manual DOM manipulation.

  • Improved Performance: React uses Virtual DOM, a lightweight representation of the actual DOM. By comparing the previous and current states of this Virtual DOM, React determines the minimal set of DOM operations needed to update the UI, resulting in faster rendering and better performance.

  • Unidirectional Data Flow: In React, data flows in a unidirectional manner, typically from parent to child components. This ensures that any change in the parent component automatically propagates to its child components, simplifying the understanding of data changes and making it easier to trace errors.

  • Reusable Components: React promotes the creation of reusable UI components. Each component encapsulates its own logic and UI, allowing developers to compose complex UIs from simpler components. This modularity not only improves code organization but also accelerates development time.

  • Versatility: React's versatility extends beyond web development to mobile app development with React Native. This framework leverages React's component-based architecture to build native mobile apps using JavaScript and React principles.

  • Developer Tools: React is supported by dedicated developer tools like the React Developer Tools extension for Chrome. These tools facilitate debugging by providing insights into component hierarchies, state changes, and performance optimizations.

ReactJS History​

When compared to other technologies on the market, React is a new technology. React was created by Jordan Walke, a software engineer at Facebook, in 2011.Initially implemented in Facebook's News Feed, its success quickly led to its adoption in Instagram, showcasing its power and versatility in building dynamic user interfaces.

React Features​

Currently, ReactJS gaining quick popularity as the best JavaScript framework among web developers. It is playing an essential role in the front-end ecosystem. The important features of ReactJS are as following.

image

JSX​

JSX is a syntax extension for JavaScript that allows developers to write HTML-like code within JavaScript. This makes it easier to create and understand the structure of React components, as it closely resembles the final output in the browser. While not mandatory, using JSX is recommended in React development because it enhances readability and simplifies the creation of user interfaces.

Components​

React components enable reusability and encapsulation by breaking down UIs into self-contained pieces with their own structure, style, and behavior. This promotes code reuse, as components can be used across different parts of the application, enhancing maintainability and reducing bugs, while ensuring a clean separation of concerns.

One-way Data Binding​

One-way data binding is a pattern where data flows in a single direction, typically from the model to the view. This ensures that the state of an application is predictable and easier to manage. In the context of JavaScript frameworks, Flux and Redux are popular architectures that facilitate one-way data binding and state management.

Flux​

Flux is an architecture pattern created by Facebook for building client-side web applications. It emphasizes unidirectional data flow and is composed of four key components:

Action:​
  • Actions are plain JavaScript objects or functions that contain the type of event and any associated data (payload). Actions are the only source of information for the store.
Dispatcher:​
  • The dispatcher is a central hub that manages all the data flow in a Flux application. When an action is created, it is dispatched to all stores that have registered with the dispatcher. The dispatcher’s role is to handle these actions and ensure they reach the appropriate store.
Store:​
  • Stores hold the application state and logic. They listen for actions from the dispatcher and update their state accordingly. Stores then emit a change event to notify the view layer to re-render. Each store manages a specific portion of the application's state.
View:​
  • The view is the presentation layer, typically composed of React components. Views listen to changes from the stores and re-render themselves accordingly. They can also generate new actions based on user interactions and send them to the dispatcher.

Virtual DOM​

A virtual DOM object is a representation of the original DOM object. It works like a one-way data binding. Whenever any modifications happen in the web application, the entire UI is re-rendered in virtual DOM representation. Then it checks the difference between the previous DOM representation and new DOM. Once it has done, the real DOM will update only the things that have actually changed. This makes the application faster, and there is no wastage of memory.

Simplicity​

ReactJS uses JSX file which makes the application simple and to code as well as understand. We know that ReactJS is a component-based approach which makes the code reusable as your need. This makes it simple to use and learn.

Performance​

ReactJS is known to be a great performer. This feature makes it much better than other frameworks out there today. The reason behind this is that it manages a virtual DOM. The DOM is a cross-platform and programming API which deals with HTML, XML or XHTML. The DOM exists entirely in memory. Due to this, when we create a component, we did not write directly to the DOM. Instead, we are writing virtual components that will turn into the DOM leading to smoother and faster performance.

React Ecosystem​

The React ecosystem is vast and diverse, encompassing a wide range of libraries and tools that enhance and extend the capabilities of React. These tools help in state management, routing, form handling, styling, and more, making React a robust framework for building complex and feature-rich applications. Here are some of the most popular libraries and tools commonly used with React:

State Management​

Redux​

Description: Redux is a state management library that provides a predictable state container for JavaScript apps. It helps manage application state and enables powerful debugging capabilities through tools like the Redux DevTools.

Key Features: Centralized state, immutability, middleware support.

MobX​

Description: MobX is a simple, scalable, and battle-tested state management solution. It uses observable data to efficiently react to state changes and update the UI.

Key Features: Observable state, actions, reactions, computed values.

Recoil​

Description: Recoil is a state management library for React developed by Facebook. It provides a set of utilities to manage state in a React application with minimal boilerplate.

Key Features: Atoms, selectors, asynchronous state management.

Routing​

React Router​

Description: React Router is the most widely used routing library for React. It allows for dynamic routing in a web application, enabling navigation between different components and views.

Key Features: Nested routes, dynamic routing, query parameters.

Form Handling​

Formik​

Description: Formik is a library that simplifies form management in React applications. It helps with form validation, error handling, and form submission.

Key Features: Form state management, validation schema support, easy integration with validation libraries like Yup.

React Hook Form​

Description: React Hook Form is a performant, flexible library for managing forms in React. It leverages React hooks for form state and validation, minimizing re-renders and improving performance.

Key Features: Minimal re-renders, easy integration with UI libraries, built-in validation support.

Styling​

Styled Components​

Description: Styled Components is a library for styling React applications using tagged template literals. It allows for writing actual CSS to style components, keeping styles scoped and maintaining a clean component structure.

Key Features: Scoped styling, theme support, dynamic styling.

Emotion​

Description: Emotion is a flexible and powerful library for writing CSS styles with JavaScript. It provides both a styled component API and a CSS-in-JS approach.

Key Features: Performant styles, server-side rendering, powerful theming capabilities.

Testing​

Jest​

Description: Jest is a JavaScript testing framework developed by Facebook, designed to ensure correctness of any JavaScript codebase. It works seamlessly with React, providing a simple and efficient way to test components and applications.

Key Features: Snapshot testing, coverage reports, mocking capabilities.

React Testing Library​

Description: React Testing Library is a testing utility that encourages testing best practices by focusing on user interactions and component behavior rather than implementation details.

Key Features: Lightweight, integrates with Jest, emphasizes testing UI from the user’s perspective.

Build and Tooling​

Create React App​

Description: Create React App (CRA) is a CLI tool that sets up a new React project with a sensible default configuration. It handles configuration for tools like Webpack, Babel, ESLint, and more.

Key Features: Zero configuration, fast setup, extensibility.

Next.js​

Description: Next.js is a React framework that enables server-side rendering and static site generation for React applications. It simplifies the process of building complex React applications with features like API routes, file-based routing, and automatic code splitting.

Key Features: Server-side rendering, static site generation, API routes, fast refresh.

The React ecosystem is continuously evolving, with new tools and libraries emerging to address various needs and challenges in modern web development. These tools help streamline the development process, enhance performance, and ensure maintainability of React applications.

Pros and Cons of ReactJS​

Today, ReactJS is the highly used open-source JavaScript Library. It helps in creating impressive web apps that require minimal effort and coding. The main objective of ReactJS is to develop User Interfaces (UI) that improves the speed of the apps. There are important pros and cons of ReactJS given as following:

Advantage of ReactJS

Easy to Learn and Use​

ReactJS is much easier to learn and use. It comes with a good supply of documentation, tutorials, and training resources. Any developer who comes from a JavaScript background can easily understand and start creating web apps using React in a few days. It is the V(view part) in the MVC (Model-View-Controller) model, and referred to as ?one of the JavaScript frameworks.? It is not fully featured but has the advantage of open-source JavaScript User Interface(UI) library, which helps to execute the task in a better manner.

Creating Dynamic Web Applications Becomes Easier​

JSX for Readability and Maintainability:​

  • JSX (JavaScript XML) allows developers to write HTML elements in JavaScript. This mixture of HTML and JavaScript makes the code more readable and maintainable. For example, instead of splitting code between HTML and JavaScript files, JSX enables developers to write them together, making it easier to understand and work with the code.

Reusable Components​

A ReactJS web application is made up of multiple components, and each component has its own logic and controls. These components are responsible for outputting a small, reusable piece of HTML code which can be reused wherever you need them. The reusable code helps to make your apps easier to develop and maintain. These Components can be nested with other components to allow complex applications to be built of simple building blocks. ReactJS uses virtual DOM based mechanism to fill data in HTML DOM. The virtual DOM works fast as it only changes individual DOM elements instead of reloading complete DOM every time.

Performance Enhancement​

Virtual DOM vs. Real DOM:​

  • React uses a virtual DOM to optimize updates and rendering. When the state of a component changes, React first updates the virtual DOM, a lightweight copy of the real DOM. It then compares this virtual DOM with a snapshot of the real DOM before applying only the necessary changes to the real DOM.Instead of re-rendering the entire DOM tree, React only updates the parts that have changed, which significantly boosts performance, especially in complex applications.

Known to be SEO Friendly​

Traditional JavaScript frameworks have an issue in dealing with SEO. The search engines generally having trouble in reading JavaScript-heavy applications. Many web developers have often complained about this problem. ReactJS overcomes this problem that helps developers to be easily navigated on various search engines. It is because React.js applications can run on the server, and the virtual DOM will be rendering and returning to the browser as a regular web page.

The Benefit of Having JavaScript Library​

Today, ReactJS is choosing by most of the web developers. It is because it is offering a very rich JavaScript library. The JavaScript library provides more flexibility to the web developers to choose the way they want.

Disadvantage of ReactJS​

The high pace of development​

Continuous Learning and Updates:​

  • The React ecosystem evolves rapidly, with frequent updates and new releases. While these updates bring improvements and new features, they also mean developers need to constantly learn and adapt. For example, React Hooks, introduced in version 16.8, brought a significant change in how state and side effects are handled.

Developers had to quickly learn and integrate this new feature, which can be challenging and time-consuming.

Poor Documentation​

Rapid Updates Leading to Outdated Information:​

  • While the official React documentation has improved, the rapid pace of updates can sometimes lead to outdated or incomplete information. For example, when new features like Concurrent Mode or Suspense are introduced, documentation might lag behind, making it difficult for developers to find accurate and up-to-date information.

Developers might need to rely on community forums, blog posts, or other unofficial sources to fill in the gaps, which can be frustrating and time-consuming.

View Part​

ReactJS Covers only the UI Layers of the app and nothing else. So you still need to choose some other technologies to get a complete tooling set for development in the project.

JSX as a barrier​

ReactJS uses JSX. It's a syntax extension that allows HTML with JavaScript mixed together. This approach has its own benefits, but some members of the development community consider JSX as a barrier, especially for new developers. Developers complain about its complexity in the learning curve.

Official Documentation​