Hello Readers, CoolMonkTechie heartily welcomes you in A Short Note Series (Real DOM Vs Virtual DOM Vs Shadow DOM In JavaScript Frameworks).
In this note series, we will understand the differences between the Real DOM, Virtual DOM and Shadow DOM in JavaScript Frameworks.
So Let’s begin.
Real DOM Vs Virtual DOM Vs Shadow DOM
Real DOM
Virtual DOM
Shadow DOM
Definition
It is the representation of a document/webpage/web application’s user interface as a tree data structure (node and objects).
It is a virtual representation of the real DOM as a tree data structure (node and objects).
The Shadow DOM can be thought of as a “DOM within a DOM”. It is a separate DOM tree with it’s own elements and styles, fully separate from the main DOM.
Usage
The Real DOM is used in every browser.
The virtual DOM is employed in many front-end frameworks and libraries like React, Vue etc.
Web components use the concept of. Shadow DOM.
The purpose of each technology
It provides a simpler, more programmatic method of representing web pages.
The virtual DOM was created to address performance problems with webpages and web application that resulted from the constant re-rendering of the whole DOM whenever DOM elements were updated.
The Shadow DOM was designed to contain and isolate DOM elements, hence preventing direct DOM leakage of those elements and their dependent data.
Implementation
Real DOM is implemented on the browser.
Virtual DOM is utilized by frameworks and libraries such as React, Vue etc.
Shadow DOM is implemented on the browser.
Principle
The DOM represents the document/webpage as nodes and objects, allowing programming languages like javascript to interact with the page using an API.
The Virtual DOM is a tree representation of the real DOM using nodes and objects and is subsequently used as a blueprint to update the real DOM.
The Shadow DOM doesn’t comprehensively represent the whole DOM. Instead of adding DOM items to the main DOM tree, it inserts subtrees of DOM elements into the document.
Real DOM Vs Virtual DOM Vs Shadow DOM
Conclusion
In this note series, we understood about Real DOM, Virtual DOM and Shadow DOM differences and usages in JavaScript Frameworks. We also understood the DOM principles about Real DOM, Virtual DOM and Shadow DOM.
Thanks for reading! I hope you enjoyed and learned about the Real DOM Vs Virtual DOM Vs Shadow DOM In JavaScript Frameworks. Reading is one thing, but the only way to master it is to do it yourself.
Please follow and subscribe us on this blog and support us in any way possible. Also like and share the article with others for spread valuable knowledge.
You can find Other articles of CoolmonkTechie as below link :
Hello Readers, CoolMonkTechie heartily welcomes you in this article (Is Composition Better Than Inheritance In React?).
In this article, we will learn about React topic ” Why Composition is better than Inheritance “. We will try to understand which works better in react, Inheritance or Composition using below points:
What are Composition and Inheritance ?
Composition vs Inheritance
Composition – Using props.children
Composition – Child Groups
Composition – Classes Work Too
What about Inheritance ?
Inheritance and Composition are two important parts of object-oriented programming when it comes to code reusability. Both of these concepts are also relevant to React components. Hence, the concept of inheritance vs composition is very important.
A famous quote about learning is :
” He who learns but does not think, is lost! He who thinks but does not learn is in great danger.“
So Let’s begin.
What are Composition and Inheritance ?
Composition and inheritance are the approaches to use multiple components together in ReactJS. This helps in code reuse. React recommends using composition instead of inheritance as much as possible and inheritance should be used in very specific cases only.
Inheritance uses the is-a relationship method. Derived components had to inherit the properties of the base component and it was quite complicated while modifying the behavior of any component. The composition aims for something better. Instead of inheriting the properties of other components, why not inherit only behavior, and add behavior to the desired component?
Composition does not inherit properties, only the behavior. This is a plus point but why? In inheritance, it was difficult to add new behavior because the derived component was inheriting all the properties of parent class and it was quite difficult to add new behavior. We had to add more uses cases. But in composition, we only inherit behavior and adding new behavior is fairly simple and easy.
For example, Let’s say we have a component to input username. We will have two more components to create and update the username field. We extended the UserNameForm component and extracted its method in child component using super.render().
Use of composition is simpler than inheritance and easy to maintain the complexity.
Composition vs Inheritance
React has a powerful composition model, and we recommend using composition instead of inheritance to reuse code between components. We can differentiate the below points between Inheritance and Composition :
Inheritance can be overused.
Composition of behavior can be simpler and easier.
React supports using composition over deep inheritance.
Inheritance inherits the properties of other components while Composition does not inherit properties, only the behavior.
In inheritance, it was difficult to add new behavior because the derived component was inheriting all the properties of parent class and it was quite difficult to add new behavior. We had to add more uses cases. But in composition, we only inherit behavior and adding new behavior is fairly simple and easy.
Composition – Using props.children
Some components don’t know their children ahead of time. This is especially common for components like Sidebar or Dialog that represent generic “boxes”.
We recommend that such components use the special children prop to pass children elements directly into their output. This lets other components pass arbitrary children to them by nesting the JSX.
Anything inside the <FancyBorder> JSX tag gets passed into the FancyBorder component as a children prop. Since FancyBorder renders {props.children} inside a <div>, the passed elements appear in the final output.
/* FancyBorder will componse with children*/
function FancyBorder(props) {
return (
<div className={'FancyBorder FancyBorder-' + props.color}>
{props.children}
</div>
);
}
/* WelcomeDialog uses FancyBorder with children*/
function WelcomeDialog() {
return (
<FancyBorder color="blue">
<h1 className="Dialog-title">
Welcome
</h1>
<p className="Dialog-message">
Thank you for visiting our spacecraft!
</p>
</FancyBorder>
);
}
We can conclude that
Any Components within <FancyBorder> become props.children
The parent component can wrap children in a <div> for layout/style
Composition – Child Groups
While this is less common, sometimes you might need multiple “holes” in a component. In such cases you may come up with your own convention instead of using children.
React elements like <Contacts /> and <Chat /> are just objects, so you can pass them as props like any other data. This approach may remind you of “slots” in other libraries but there are no limitations on what you can pass as props in React.
Sometimes components have children in several places
Assigning the child components to prop names can help organize
Composition – Classes Work Too
Sometimes we think about components as being “special cases” of other components. For example, we might say that a WelcomeDialog is a special case of Dialog.
In React, this is also achieved by composition, where a more “specific” component renders a more “generic” one and configures it with props.
Composition works equally well for components defined as classes.
Specific Components can configure General Components
Props can be used to configure
What about Inheritance ?
Facebook doesn’t use inheritance beyond initial Component Classes
Frontends can be built using a mixture of ‘general’ and ‘specific’ components
Use Props to pass specific attributes and children to render specific behavior
Behavior shared within Components such as logic or utilities can be shared as JavaScript libraries or modules
Using import is more useful and less restricting then extends
That’s all about in this article.
Conclusion
In this article, We understood which works better in react, Inheritance or Composition. Inheritance and composition both can be used for code reusability and for enhancing components but according to the core React team, we should prefer composition over inheritance.
Thanks for reading ! I hope you enjoyed and learned about Composition concept is better than Inheritance in React. Reading is one thing, but the only way to master it is to do it yourself.
Please follow and subscribe us on this blog and and support us in any way possible. Also like and share the article with others for spread valuable knowledge.
You can find Other articles of CoolmonkTechie as below link :
Hello Readers, CoolMonkTechie heartily welcomes you in this article.
In this article, we will learn about how are Javascript Equality Operators useful for Comparison. Comparing any two values for equality/inequality is one of the basic functionalities provided by any programming language. Each programming language provides some operators to compare all kinds of operands. JavaScript also inherits and extends the same concept. It provides two variants of operators for comparing whether two operands are equal. This article will show the following Javascript Equality Operators for Comparison with the example as below:
Equality (==) Operator
Strict Equality (===) Operator
InEquality (! =) Operator
Strict InEquality (! ==) Operator
A famous quote about learning is :
” We now accept the fact that learning is a lifelong process of keeping abreast of change. And the most pressing task is to teach people how to learn. “
So Let’s begin.
1. Equality (==) Operator
In Javascript, the ‘==’ operator is also a loose equality operator that mainly compares two values on both sides, and then return true or false.
Syntax:
operand1 == operand2
It is type coercion, which means that the two values are compared only after attempting to convert them into the same type. If there is a type mismatch between the operands, it first converts the operands to the same type if they are not of the same type, then applies strict comparison. If both operands are objects, in this case, JavaScript carries out a comparison of internal references, which are equal when operands refer to the same object in memory.
Equality (==) Operator–Example 1
let var1 = 5;let var2 = 5;document.write(var1 == var2);//Output will be true
In the above example, we have taken variables that are of both number type.When we compare them using the “==” operator, JavaScript will just compare the values directly and will not do any type of conversion.
Equality (==) Operator–Example 2
let var1 = 5;let var2 = '5';document.write(var1 == var2);//Output will be true
In the above example, var1 is of number type, and var2 is of string type. Before comparing both the variables, JavaScript will first convert the types of variables, so both the variables have the same type. In this example, it will convert the string variable to a number and then will make the comparison of both the numbers. So, ideally, it just compares the values of the variables and not the data type of the variable.
2. Strict Equality (===) Operator
In Javascript, the ‘===’ operator is also a triple equals or strict equality or identity operator.
Syntax:
operand1 === operand2
The result of the identity operator is true if the operands are strictly equal with no type-conversion. During this comparison, the compiler doesn’t convert the value implicitly; instead of this, it will compare both the value and data type of the operands.
Strict Equality (===) Operator–Example 1
let var1 = 5;let var2 = 5;document.write(var1 === var2);//Output will be true
In the above example, we have taken variables, both variable “var1″ and var2” of number types. Here, as both the values of variables and their data type are the same, JavaScript will return the result of comparison true.
Strict Equality (===) Operator–Example 2
let var1 = 5;let var2 = '5';document.write(var1 === var2);//Output will be false
In the above example, we have taken var1 is of number type, and var2 is of string type. Here, === operator is not only checking the value but also the data type, and as the data type of both the variables is not the same, the output will be false.
3. InEquality (! =) Operator
In Javascript, the ‘! =’ operator is known as a loose inequality operator, which mainly compares two values on both sides and then returns true if the values are not equal and false if the values are equal.
Syntax:
operand1 != operand2
Similar to the Equality operator, this operator also converts the type of both the operands if needed. If there is a type mismatch between the operands, it first converts the operands to the same type and then applies comparison.
InEquality (! =) Operator–Example 1
let var1 = 5;let var2 = 3;document.write(var1 != var2);//Output will be true
In the above case, we have taken variables, both of which are ofnumber type.When we compare them using the “! =” operator, JavaScript will just compare the operands based on their values. In this scenario, no type-conversion happens, as both the operands are of the same type.
InEquality (!=) Operator–Example 2
let var1 = 5;let var2 = '5';document.write(var1 != var2);//Output will be false
In the above example, var1 is of number type, and var2 is of string type. Before comparing both the variables, JavaScript will first convert the data type of variables, so that both the variables have the same data type. In this example, it will convert the string variable to the number and then will make the comparison of both the numbers. So, ideally, it just compares the values of the variables and not the data type of the variable. As the value of both the variables is 5, so the “! =” operator will return result as false.
4. Strict InEquality (! ==) Operator
In Javascript, the ‘!==’ operator is known as a notdouble equalsor strict inequalityoperator. If the operands are strictly unequal with no type-conversion then the identity operator results true. During this comparison, the compiler doesn’t convert the data type of operands implicitly. Instead of this, it will compare both the values as well as the data type of operands.
Syntax:
operand1 !== operand2
Strict InEquality (! ==) Operator – Example 1
let var1 = 5;let var2 = 5;document.write(var1 !== var2);//Output will be false
In the above example, we have taken variables, both variable “var1″ and var2” of number types. Here, as both the values of variables and their data type are the same, JavaScript will return, the result of the comparison is false.
Strict InEquality (! ==) Operator–Example 2
let var1 = 5;let var2 = '5';document.write(var1 !== var2);//Output will be true
In the above example, we have taken var1 is of number type, and var2 is of string type. Here, ! == operator is not only checking the value but also the data type, and as the data type of both the variables is not the same, the output will be true.
That’s all about in this article.
Conclusion
In this article, we understood about how are Javascript Equality Operators useful for Comparison. We conclude that :
The Equality (==) and InEquality (! =) Operators compares the operands only based on their values and ignores the data types of the operands.
The Strict Equality (===) and Strict InEquality (! ==) Operators compare the operands based on both values as well as data types of the operands.
Thanks for reading !! I hope you enjoyed and learned about Equality Operators concept in JavaScript. Reading is one thing, but the only way to master it is to do it yourself.
Please follow and subscribe us on this blog and support us in any way possible. Also like and share the article with others for spread valuable knowledge.
You can find Other articles of CoolmonkTechie as below link :
Hello Readers, CoolMonkTechie heartily welcomes you in this article.
In this article, we will learn about promises in javascript. A promise in real life is just an assurance about ‘something.’ So what happens when somebody makes a promise to us? They give us a guarantee based on which we can plan something. Now, the promise can either be kept or broken. So, when we keep a promise, we expect something out of that promise. We can make use of the output of a promise for our further actions or plans. But, when a promise breaks, we would like to know why the person who made the promise was not able to keep up his side of the bargain. JavaScript provides a kind of similar concept of “Promises” for handling the asynchronous calls.
In this article, we will discuss the below items to understand the concepts of promises in JavaScript:
What are Promises in JavaScript?
When to use Promises in JavaScript?
How Promises works in JavaScript?
Create a Promise in JavaScript
How to consume a Promise in JavaScript?
A famous quote about learning is :
” I am always ready to learn although I do not always like being taught. “
So Let’s begin.
What are Promises in JavaScript?
A Promise in JavaScript is an object that holds the future value of an asynchronous operation.
For example, if we are requesting some data from a server, the promise promises us to get that data that we can use in the future.
A promise object can have the following states:
Pending: it is an initial state, where the result is not ready, and it is waiting for the asynchronous operation to get finished.
Resolved/Fulfilled: it means that performed action completed successfully. i.e., Function returned promised value.
Rejected: it means that performed action failed or an error occurred. i.e., function did not return the promised value.
When to use Promises in JavaScript?
Now let’s understand what was the need for the promise in JavaScript, as the async operations would have handled using the callbacks itself. Callback function is used to handle asynchronous execution. A callback function indicates the operation which JavaScript should execute once an asynchronous operation finishes.
Here is the simplest example of a callback function as below:
<html>
<body> Demonstrating callback in javascript:</br>
<script type="text/javascript">
function i_take_1_sec() {
return setTimeout(() => {
document.write('I was no: 2 and I take 1 second</br>')
}, 1000);
}
function i_take_10_sec(callback) {
return setTimeout(() => {
document.write('I was no: 1 and I take 10 seconds</br>')
callback()
}, 10000);
}
function run (){
i_take_10_sec(i_take_1_sec);
}
run();
</script>
</body>
</html>
The output of the above callback function example is :
How Promises works in JavaScript?
To understand how exactly promises works, let us take the example, Consider we are making a promise to our mother saying that we are going to clean up our room by the end of the day. So two possible things can happen either we will be going to clean the room, or we are going not to clean the room and break our promise. Let’s write that promise in the JavaScript.
let promiseCleanRoom = new Promise(function(resolve,reject){
cleanRoom = true;
if(cleanRoom){
resolve('Cleaned the Room');
}else{
reject('Broke the promise');
}
});
The above code block shows how to create the promise. i.e., when this promise executes, then it will give either resolve status or reject status based on the cleanRoom value.
In the above snippet, it shows how to utilize the created promise, and there is “.then,” a method that will perform some of the action only when a given promise is fulfilled or resolved. In this case, it will print the result sent by promise when it resolves, i.e., Cleaned the Room.
There is one more case that will happen if the promise got broken or some error occurred in that case. Then we can use the “.catch ” block that will allow handling the broken or instances of error.
promiseCleanRoom.then((result)=>{
console.log(result)
}).catch((result)=>{
console.log(result) //will execute if promise is rejected or errored out
})
Suppose, if the promise breaks, then it will execute the catch block by skipping the then block, and output will be “Broke the promise”.
Create a Promise in JavaScript
As we discussed above, A Promise in JavaScript is an object representing the eventual completion or failure of an asynchronous operation. Its syntax looks like below:
const promise = new Promise(function(resolve,reject){
//do something
});
Here we create a new promise using the Promise constructor, which takes a single argument, a callback function, also known as executor function, which in turn takes two callbacks functions, resolve, and reject.
The executor function immediately executes when a promise creates. The promise resolves by calling the resolve() method and is rejected by calling the reject() method.
Let’s try to understand the usage and working of Promise in JavaScript with the help of following code snippet.
<html>
<body> Demonstrating promise in javascript:</br>
<script type="text/javascript">
function i_take_10_sec()
{
return new Promise((resolve, reject)=>{
setTimeout(() => {
resolve('I was no: 1 and I take 10 seconds');
}, 10000);
})
}
function i_take_1_sec()
{
return new Promise((resolve, reject)=>{
setTimeout(() => {
resolve('I was no: 2 and I take 1 second');
}, 1000);
})
}
function i_take_5_sec(callback)
{
return new Promise((resolve, reject)=>{
setTimeout(() => {
resolve('I was no: 3 and I take 5 second')
}, 5000);
})
}
function i_take_7_sec(callback)
{
return new Promise((resolve, reject)=>{
setTimeout(() => {
resolve('I was no: 4 and I take 7 second')
}, 7000);
})
}
function run()
{
i_take_10_sec()
.then((result) => {
console.log(result);
return i_take_1_sec()
})
.then((result) => {
console.log(result);
return i_take_5_sec()
})
.then((result) => {
console.log(result);
return i_take_7_sec()
})
.then((result)=>{
console.log(result);
})
}
run();
</script>
</body>
</html>
The Developer Tools output of the above example code snippet is :
As seen in the above example, each of the functions returns a promise that chains to the next using “.then().” The code flow appears much prettier and understandable in this case.
Now consider a scenario that one of the promises rejects. So, in that scenario, it will raise an error and will not invoke the other chained function calls.
<html>
<body> Demonstrating promise in javascript:</br>
<script type="text/javascript">
function i_take_10_sec()
{
return new Promise((resolve, reject)=>{
setTimeout(() => {
resolve('I was no: 1 and I take 10 seconds');
}, 10000);
})
}
function i_take_1_sec()
{
return new Promise((resolve, reject)=>{
setTimeout(() => {
resolve('I was no: 2 and I take 1 second');
}, 1000);
})
}
function i_take_5_sec(callback)
{
return new Promise((resolve, reject)=>{
setTimeout(() => {
reject('I was no: 3 and I take 5 second')
}, 5000);
})
}
function i_take_7_sec(callback)
{
return new Promise((resolve, reject)=>{
setTimeout(() => {
resolve('I was no: 4 and I take 7 second')
}, 7000);
})
}
function run()
{
i_take_10_sec()
.then((result) => {
console.log(result);
return i_take_1_sec()
})
.then((result) => {
console.log(result);
return i_take_5_sec()
})
.then((result) => {
console.log(result);
return i_take_7_sec()
})
.then((result)=>{
console.log(result);
})
}
run();
</script>
</body>
</html>
The Developer Tools output of the above example code snippet is :
As we can see from the above screenshot that JavaScript raised an “Uncaught” error after invoking the method “i_take_5_sec,” and no further code statements execute. So, this confirms that, once the promise is “rejected,” it will lead to failure of all the further chained commands.
How to consume a promise in JavaScript?
Promises consume by registering functions using .then,.catch, and .finally methods. A Promise object serves as a link between the executor and the consuming functions, which will receive the result or error, and the consuming functions can use any of the .then, .catch, or .finally methods. Let’s see the usage of all these methods in the below sections:
How to use .then() as a consumer function?
The .then() method invokes when a promise is either resolved or rejected. Its syntax looks like below:
.then(function(result){
//statements when the promise is resolved successfully
}, function(error){
//statements when the prmise was rejected or raised an error
})
We can understand the primary usage of the “.then()” method with the help of the following figure:
Let comprehend in this way, assume an if-else statement where code in if block will execute when the given condition is true; otherwise, it will execute the else block. Similarly, the “then” method will take two functions as parameters where the first function will run when a promise resolves successfully, or it will execute the second method when a promise rejects or raise an error.
Let’s understand the usage and implementation of the “.then() consumer method,” by modifying the above-written program as follows:
<html>
<body> Demonstrating promise consumer using .then() method in javascript:</br>
<script type="text/javascript">
function i_take_10_sec()
{
return new Promise((resolve, reject)=>{
setTimeout(() => {
resolve('I was no: 1 and I take 10 seconds');
}, 10000);
})
}
function i_take_5_sec(callback)
{
return new Promise((resolve, reject)=>{
setTimeout(() => {
reject('I was no: 3 and I take 5 second')
}, 5000);
})
}
function run()
{
i_take_10_sec()
.then((result) => {
console.log(result);
return i_take_5_sec()
})
.then((result)=>{
console.log(result);
},()=>{
console.log('Error Raised')
})
}
run();
</script>
</body>
</html>
The Developer Tools output of the above example code snippet is :
We can see from the above screenshot that, as the “i_take_5_sec()” method resulted in the promise to be rejected, so the call flow in the run method invoked the second function, instead of the first function. So, in this way, a user can control the flow of program execution using the “.then()” method depending on the expected outputs of the promise.
But passing two functions as parameters for then method looked somewhat confusing. Therefore, to overcome this, the “.catch” block or function was introduced where the catch block will explicitly handle when there is rejection, or some error has occurred.
How to use .catch() as a consumer function?
The .catch() method invokes when a promise rejects, or some error occurs in the execution. Its syntax looks like below:
Syntax:
.catch(function(error){
//Statements to handle error raised
})
The basic usage of the “.catch()” method can be understood with the help of the following figure:
As is evident from the above image, in case of .catch() method specified, it will invoke the “.catch” block when the promise gets rejected.
Lets understand the usage and implementation of the “.catch() consumer method,” by modifying the above-written program as follows:
<html>
<body> Demonstrating promise consumer using .catch() method in javascript:</br>
<script type="text/javascript">
function i_take_10_sec()
{
return new Promise((resolve, reject)=>{
setTimeout(() => {
resolve('I was no: 1 and I take 10 seconds');
}, 10000);
})
}
function i_take_5_sec(callback)
{
return new Promise((resolve, reject)=>{
setTimeout(() => {
reject('I was no: 3 and I take 5 second')
}, 5000);
})
}
function run()
{
i_take_10_sec()
.then((result) => {
console.log(result);
return i_take_5_sec()
})
.then((result)=>{
console.log(result);
}).catch(()=>{
console.log('Error Raised')
})
}
run();
</script>
</body>
</html>
The Developer Tools output of the above example code snippet is :
We can see from the above screenshot that, as the “i_take_5_sec()” method resulted in the promise to be rejected, so the call flow raised the exception, which happened in the .catch() block. Also, as the exception occurred properly, it didn’t block the call flow and still executed the next part in the .then() part resulting from the printing of “Done.” It makes it clear that using the .catch() block ensures that the further chained calls will still execute, even though one of the intermediate calls resulted in an error or exception.
How to use .finally() as a consumer function?
As we used to have the finally block in a regular try{…}catch{…}of exception handling, there’s finally in promises also. This consumer function always executes when the promise settles: be it resolve or reject. The finally block a good handler for performing cleanup actions, which we always expect to execute. Its syntax looks like below:
.finally(() => {
// Statements which are expected to be executed always
})
The basic usage of the “.catch()” method can be understood with the help of the following figure:
As we can see from the above picture, the “finally” block will always execute, no matter whether the promise has been resolved or rejected.
Let’s understand the usage and implementation of the “.finally() consumer method,” by modifying the above-written program as follows:
<html>
<body> Demonstrating promise consumer using .finally() method in javascript:</br>
<script type="text/javascript">
function i_take_10_sec()
{
return new Promise((resolve, reject)=>{
setTimeout(() => {
resolve('I was no: 1 and I take 10 seconds');
}, 10000);
})
}
function i_take_5_sec(callback)
{
return new Promise((resolve, reject)=>{
setTimeout(() => {
reject('I was no: 3 and I take 5 second')
}, 5000);
})
}
function run()
{
i_take_10_sec()
.then((result) => {
console.log(result);
return i_take_5_sec()
})
.then((result)=>{
console.log(result);
}).catch(()=>{
console.log('Error Raised')
}).finally(()=>{
console.log('Completed Execution')
})
}
run();
</script>
</body>
</html>
The Developer Tools output of the above example code snippet is :
We can see from the above screenshot that, as the “i_take_5_sec()” method resulted in the promise to be rejected, due to which the exception raised and the next .then() method of the “Done” block was not executed. But still, we can see from the output that the finally() block executed. So, it makes it clear that, whether the promise returns a resolved, rejected or and error state, the “finally()” block will always be executed.
How to use Promise.all() as a consumer function?
If we want to execute multiple promises in parallel and want to wait for the completion of all the promises before proceeding further, we can use the “.all” function provided by the Promises in JavaScript. It takes an array of promises function and executes all functions simultaneously / parallelly and wait until all promises are either resolve or reject. Its syntax looks like below:
Promise.all([array of promises]);
Let’s understand the usage of “Promise.all” with the help of the following example:
<html>
<body> Demonstrating promise all() method in javascript:</br>
<script type="text/javascript">
function i_take_10_sec()
{
return new Promise((resolve, reject)=>{
setTimeout(() => {
console.log('I was no: 1 and I take 10 second')
resolve('I was no: 1 and I take 10 seconds');
}, 10000);
})
}
function i_take_5_sec(callback)
{
return new Promise((resolve, reject)=>{
setTimeout(() => {
console.log('I was no: 2 and I take 5 second')
resolve('I was no: 2 and I take 5 second')
}, 5000);
})
}
function i_take_7_sec(callback)
{
return new Promise((resolve, reject)=>{
setTimeout(() => {
console.log('I was no: 3 and I take 7 second')
resolve('I was no: 3 and I take 7 second')
}, 7000);
})
}
function run()
{
Promise.all([i_take_10_sec(),i_take_5_sec(),i_take_7_sec()]).then(()=>{
console.log("All finished");
})
}
run();
</script>
</body>
</html>
The Developer Tools output of the above example code snippet is :
As we can see that all the promises are executing simultaneously and will wait until all promises either resolve or reject.
we aware that Promise.all() doesn’t ensure any ordering of promises. It just executes all of the promises in parallel.
How to use Promise.race() as a consumer function?
If we want to execute multiple promises in parallel but don’t want to wait for the completion of all the promises before proceeding further, we can use the “.race” function provided by the Promises in JavaScript. It just waits for completion of any one promise, which returns first. It will take an array of promises function and execute all functions simultaneously and wait until any one of the promises is either resolve or reject. Its syntax looks like below:
Promise.race([array of promises])
Let’s understand the usage of “Promise.race” with the help of the following example:
<html>
<body> Demonstrating promise race() method in javascript:</br>
<script type="text/javascript">
function i_take_10_sec()
{
return new Promise((resolve, reject)=>{
setTimeout(() => {
console.log('I was no: 1 and I take 10 second')
resolve('I was no: 1 and I take 10 seconds');
}, 10000);
})
}
function i_take_5_sec(callback)
{
return new Promise((resolve, reject)=>{
setTimeout(() => {
console.log('I was no: 2 and I take 5 second')
resolve('I was no: 2 and I take 5 second')
}, 5000);
})
}
function i_take_7_sec(callback)
{
return new Promise((resolve, reject)=>{
setTimeout(() => {
console.log('I was no: 3 and I take 7 second')
resolve('I was no: 3 and I take 7 second')
}, 7000);
})
}
function run()
{
Promise.race([i_take_10_sec(),i_take_5_sec(),i_take_7_sec()]).then(()=>{
console.log("All finished");
})
}
run();
</script>
</body>
</html>
The Developer Tools output of the above example code snippet is :
In the above example, we can see that as soon as one promise(i_take_5 sec) resolves, it exits from then function.
That’s all about in this article.
Conclusion
In this article, We understood about Promises in JavaScript. We conclude that :
Promises can handle the asynchronous calls in JavaScript.
A promise will be “pending” when executed and will result in “resolved” or “rejected,” depending on the response of the asynchronous call.
Promises avoid the problem of “callback hell,” which happens due to nested callback functions.
Thanks for reading !! I hope you enjoyed and learned about Promises Concept in javascript. Reading is one thing, but the only way to master it is to do it yourself.
Please follow and subscribe us on this blog and and support us in any way possible. Also like and share the article with others for spread valuable knowledge.
If you have any comments, questions, or think I missed something, feel free to leave them below in the comment box.
Hello Readers, CoolMonkTechie heartily welcomes you in this article (How To Pass Arbitrary Parameters To A Function In JavaScript ?).
In this article, we will learn how to pass arbitrary parameters to a function using Rest Parameters and Spread Operator in JavaScript. All the programming languages provide different ways to pass an arbitrary, indefinite number of parameters to a function. Javascript has also provided concepts that make the “passing of arbitrary parameters” to a function very easy. We will also understand how to handle the arbitrary parameters using the “Rest parameter” in JavaScript.
In this article, we will discuss the below items to understand the concepts of handling the arbitrary parameters:
Handle arbitrary parameters using the “arguments” variable in JavaScript
Handle the arbitrary parameters using the “rest parameter” in JavaScript
Expand iterable objects using the “spread operator” in JavaScript
A famous quote about learning is :
” There is no end to education. It is not that you read a book, pass an examination, and finish with education. The whole of life, from the moment you are born to the moment you die, is a process of learning.”
So Let’s begin.
Handle arbitrary parameters using the “arguments” variable in JavaScript
Arguments are a special type of in-built variable available in JavaScript, which can handle an arbitrary number of parameters in a function. Consider a scenario where the function definition doesn’t accept any parameters, but at run time, the caller wants to pass some parameters. Such kind of parameters can be accessed in the function definition using the “arguments“ variable. One can access the arguments with the help of the index of the arguments variable.
Let’s understand the usage of “arguments” with the help of the following example:
In the above example, We can see that the display method doesn’t have any parameters. Still, while calling, we are sending two parameters, and we can access it by using the “arguments“ variable with the help of the index.
Even though the “arguments” variable is both array-like and iterable, it’s not an array. Additionally, it does not support array methods, so we can’t call arguments.map(...) for example.
Handle arbitrary parameters using the “rest parameter” in JavaScript
The “rest parameter” is the advanced way provided by JavaScript to handle the arbitrary number of parameters. Its syntax looks like below:
function functionName(...args){
//Statements need to get executed
}
Let’s try to understand the details and usage of the rest parameter with the help of the following example:
Consider a case where we need to perform a multiplication operation; the function will look like:
function multiply(variable1, variable2){
return variable1*variable2;
}
Now, the above code perfectly works when there are only 2 arguments, But imagine there is a situation where we need to multiply n number of variables, and n can be different for each time one invokes the function. In this case, the number of arguments entirely depends on the caller.
To achieve this, we can use the rest parameter, as shown below:
Example: when the function just accepts the “rest” parameter
<html>
<body>
Demonstrating rest operator in javascript
</br>
</br>
<script type='text/javascript'>
function multiply(...variables){
var output =1;
for(x of variables){
output*=x;
}
return output;
}
document.write("Multiplication of 2 variables 3 and 5 is "+multiply(3,5));
document.write("</br>");
document.write("Multiplication of 3 variables 3,2 and 5 is "+multiply(3,2,5));
document.write("</br>");
document.write("Multiplication of 0 variables is "+multiply());
</script>
</body>
</html>
In the above example, we can see that there is only one multiply function, but it can take n number of variables, and the caller will decide these variables. The “rest” parameter is being specified by the “...variables” in the multiply method, and it can accept zero or more parameters.
The “rest” parameter can be combined with other parameters of the function as well, but it will always be the last parameter of the function. Let’s understand the same with the help of the following example:
Example: when the function accepts named parameters with the rest parameter
Let’s consider an example that takes two mandatory parameters, and the last variable is a “rest” parameter. The following code snippet shows the usage of the “rest” parameter as the last parameter of the function:
<html>
<body>
Demonstrating rest operator in javascript
</br>
</br>
<script type='text/javascript'>
function multiply(var1,var2,...variables){
document.write(var1 +" "+var2);
document.write("</br>");
var output =1;
for(x of variables){
output*=x;
}
return output;
}
document.write("Multiplication of 2 variables 3 and 5 is "+multiply("Blog","Testing",3,5));
document.write("</br>");
document.write("Multiplication of 3 variables 3,2 and 5 is "+multiply("Java","Script",3,2,5));
document.write("</br>");
document.write("Multiplication of 0 variables is "+multiply("Blog","Output"));
</script>
</body>
</html>
As we can see in the above code snippet, the multiple functions are accepting var1 and var2 as mandatory parameters, and the last parameter “…variables” is the “rest” parameter. The user can invoke the function by passing the two necessary parameters and the rest parameters as any arbitrary number of parameters.
Expand iterable objects using the “spread operator” in JavaScript
Till now, we have seen how to get an array from the list of parameters. But sometimes we need to do precisely the reverse.
For example, the built-in function Math.max that returns the greatest number from a list:
Math.max(3, 5, 1) // Returns 5
Now let’s say we have an array [3,5,1]. How do we call “Math.max” with it? Passing it “as is” won’t work, because “Math.max” expects a list of numeric arguments and not a single array object:
let arr = [3, 5, 1];
Math.max(arr); // NaN
And surely we can’t manually list items in the code Math.max(arr[0], arr[1], arr[2]), because we may be unsure how many parameters are there. When the function invokes, there could be a lot, or there could be no parameters.
The spread syntax can handle such a scenario. It appears similar to rest parameters, also uses “…” but does quite the opposite. When “…arr” is used in the function call, it “expands” an iterable object “arr” into the list of arguments. Its syntax looks like below:
Syntax:
var array=[va1,val2,val3…,valN];
callingFunction(...array); //...variablename convert array to list of arguments
For “Math.max” it will look like:
let arr = [3, 5, 1];
Math.max(...arr); // 5 (spread turns array into a list of arguments)
We also can pass multiple iterable objects this way:
let arr1 = [1, -2, 3, 4];
let arr2 = [8, 3, -8, 1];
Math.max(...arr1, ...arr2); // 8
We can even combine/ join the spread syntax with normal values:
Let’s understand the detailed usage of the “spread” syntax with the help of the following example:
Example:
<html>
<body>
Demonstrating spread operator in javascript
</br>
</br>
<script type='text/javascript'>
function display(...args){//This is rest operator
document.write("Total number of parameters are "+args.length);
document.write("</br>");
for(x of args){
document.write(x+" ");
}
}
var data = ["Blog","CoolmonkTechie","JavaScript","Tutorial"];
display(...data);//This is spread operator
</script>
</body>
</html>
As we can see in the above example, we are passing data array to the “display” function with the help of the spread operator, and the data array converts to a list of arguments.
That’s all about in this article.
Conclusion
In this article, We understood how to pass arbitrary parameters to a function using Rest Parameters and Spread Operator in JavaScript. We conclude that :
The “arguments” is a special array-like object that contains all the parameters passed by their index.
The “rest” parameters pass and handle an arbitrary number of arguments.
The “spread” operator is used to convert the iterable objects like an array to a list of independent parameters.
Thanks for reading !! I hope you enjoyed and learned about Rest Parameters and Spread Operator Concept in javascript. Reading is one thing, but the only way to master it is to do it yourself.
Please follow and subscribe us on this blog and and support us in any way possible. Also like and share the article with others for spread valuable knowledge.
You can find Other articles of CoolmonkTechie as below link :
Hello Readers, CoolMonkTechie heartily welcomes you in this article (How To Use Axios with ReactJS ?).
In this article, we will understand how to use Axios with ReactJS. Many projects on the web need to interface with a REST API at some stage in their development. Axios is a lightweight HTTP client based on the $http service within Angular.js v1.x and is similar to the native JavaScript Fetch API. In this article, we will see examples of how to use Axios to access the popular JSON Placeholder API within a React application.
A famous quote about learning is :
” Change is the end result of all true learning.”
So Let’s begin.
Introduction
Axios is promise-based, which gives you the ability to take advantage of JavaScript’s async and await for more readable asynchronous code.
We can also intercept and cancel requests, and there’s built-in client-side protection against cross-site request forgery.
Prerequisites
To follow along with this article, we’ll need the following:
Node.js version 10.16.0 installed on our computer.
A new React project set up with Create React App.
It will also help to have a basic understanding of JavaScript along with a basic knowledge of HTML and CSS.
Steps to Use Axios library
Step 1 – Adding Axios to the Project
In this section, we will add Axios to the axios-tutorial React project. To add Axios to the project, open our terminal and change directories into our project:
$ cd axios-tutorial
Then run this command to install Axios:
$ npm install axios
Next, we will need to import Axios into the file we want to use it in.
Step 2 – Making a GET Request
In this example, we create a new component and import Axios into it to send a GET request.
Inside the src folder of our React project, create a new component named PersonList.js:
First, we import React and Axios so that both can be used in the component. Then we hook into the componentDidMount lifecycle hook and perform a GET request.
We use axios.get(url) with a URL from an API endpoint to get a promise which returns a response object. Inside the response object, there is data that is then assigned the value of person.
We can also get other information about the request, such as the status code under res.status or more information inside of res.request.
Step 3 – Making a POST Request
In this step, we will use Axios with another HTTP request method called POST.
Remove the previous code in PersonList and add the following to create a form that allows for user input and subsequently POSTs the content to an API:
Inside the handleSubmit function, we prevent the default action of the form. Then update the state to the user input.
Using POST gives us the same response object with information that we can use inside of a then call.
To complete the POST request, we first capture the user input. Then we add the input along with the POST request, which will give us a response. We can then console.log the response, which should show the user input in the form.
Step 4 – Making a DELETE Request
In this example, we will see how to delete items from an API using axios.delete and passing a URL as a parameter.
Change the code for the form from the POST example to delete a user instead of adding a new one:
Again, the res object provides us with information about the request. We can then console.log that information again after the form is submitted.
Step 5 – Using a Base Instance in Axios
In this example, we will see how we can set up a base instance in which we can define a URL and any other configuration elements.
Create a separate file named api.js. Export a new axios instance with these defaults:
src/api.js
import axios from 'axios';
export default axios.create({
baseURL: `http://jsonplaceholder.typicode.com/`
});
Once the default instance is set up, it can then be used inside of the PersonList component. We import the new instance like this:
src/PersonList.js
import React from 'react';
import axios from 'axios';
import API from '../api';
export default class PersonList extends React.Component {
handleSubmit = event => {
event.preventDefault();
API.delete(`users/${this.state.id}`)
.then(res => {
console.log(res);
console.log(res.data);
})
}
}
Because http://jsonplaceholder.typicode.com/ is now the base URL, we no longer need to type out the whole URL each time we want to hit a different endpoint on the API.
Step 6 – Using async and await
In this example, we will see how we can use async and await to work with promises.
The await keyword resolves the promise and returns the value. The value can then be assigned to a variable.
In this code sample, the .then() is replaced. The promise is resolved, and the value is stored inside the response variable.
That’s all about in this article.
Conclusion
In this article, We understood how to use Axios with ReactJS. We explored several examples on how to use Axios inside a React application to create HTTP requests and handle responses.
Thanks for reading ! I hope you enjoyed and learned about the Axios library usage in ReactJS. Reading is one thing, but the only way to master it is to do it yourself.
Please follow and subscribe to the blog and support us in any way possible. Also like and share the article with others for spread valuable knowledge.
You can find Other articles of CoolmonkTechie as below link :
Hello Readers, CoolMonkTechie heartily welcomes you in this article.
In this article, we will understand about the rules of React Hooks and how to effectively start using them in our projects. We will discuss the two most important rules of React Hooks and how to effectively think in Hooks.
” React Hooks are a new addition in React 16.8 that let you use state and other React features without writing a class component. In other words, Hooks are functions that let you “hook into” React state and lifecycle features from function components. (They do not work inside class components.)”
A famous quote about learning is :
” The more I live, the more I learn. The more I learn, the more I realize, the less I know. “
So Let’s begin.
What is React Hook?
Hooks are a new addition in React 16.8. They let you use state and other React features without writing a class. It mainly uses to handle the state and side effects in react functional component. React Hooks are a way to use stateful functions inside a functional component. Hooks don’t work inside classes — they let you use React without classesReact provides a few built-in Hooks like useState and useEffect. The React hooks do :
Best practices
Easy to under understand
Easy to test
Increases the performance and so on.
Why React Hook?
There are two reasons to use React hooks :
The first main reason is the Introduce state in a functional component. We know that the states cannot be used in functions. But with hooks, we can use states.
Another reason is the handle side effect in react component. It means, now we can use newly introduced state such as useEffect.
But do we should know for some scenarios, there are 3 places where react fails. While Reuse logic between components :
Has Huge components
Confusing
Rules Of React Hooks
Hooks are JavaScript functions, but we need to follow two rules when using them :
Call Hooks at the top level;
Only call Hooks from React components.
Let’s look at these rules in more detail :
1. Call Hooks At The Top Level
Don’t call Hooks inside loops, conditions, or nested functions. Always use Hooks at the top level of your React function. By following this rule, we ensure that Hooks are called in the same order each time a component renders. That’s what allows React to correctly preserve the state of Hooks between multiple useState and useEffect calls.
Let’s make a Form component which will have two states:
accountName
accountDetail
These states will have default values, we’ll make use of the useEffect hook to persist the state to either the local storage of our browser or to the title of our document.
Now, this component will be maybe to successfully manage its state if it remains the same between multiple calls of useState and useEffect.
function Form() {
// 1. Use the accountName state variable
const [accountName, setAccountName] = useState('Arun');
// 2. Use an effect for persisting the form
useEffect(function persistForm() {
localStorage.setItem('formData', accountName);
});
// 3. Use the accountDetail state variable
const [accountDetail, setAccountDetail] = useState('Active');
// 4. Use an effect for updating the title
useEffect(function updateStatus() {
document.title = accountName + ' ' + accountDetail;
});
// ...
}
If the order of our Hooks changes (which can be possible when they are called in loops or conditionals), React will have a hard time figuring out how to preserve the state of our component.
// ------------
useState('Arun') // 1. Initialize the accountName state variable with 'Arun'
useEffect(persistForm) // 2. Add an effect for persisting the form
useState('Active') // 3. Initialize the accountdetail state variable with 'Active'
useEffect(updateStatus) // 4. Add an effect for updating the status
// -------------
// Second render
// -------------
useState('Arun') // 1. Read the accountName state variable (argument is ignored)
useEffect(persistForm) // 2. Replace the effect for persisting the form
useState('Active') // 3. Read the accountDetail state variable (argument is ignored)
useEffect(updateStatus) // 4. Replace the effect for updating the status
// ...
That’s the order React follows to call our hooks. Since the order remains the same, it will be able to preserve the state of our component. But what happens if we put a Hook call inside a condition?
// We're breaking the first rule by using a Hook in a condition
if (accountName !== '') {
useEffect(function persistForm() {
localStorage.setItem('formData', accountName);
});
}
The accountName !== '' condition is true on the first render, so we run this Hook. However, on the next render the user might clear the form, making the condition false. Now that we skip this Hook during rendering, the order of the Hook calls becomes different:
useState('Arun') // 1. Read the accountName state variable (argument is ignored)
// useEffect(persistForm) // This Hook was skipped!
useState('Active') // 2 (but was 3). Fail to read the accountDetails state variable
useEffect(updateStatus) // 3 (but was 4). Fail to replace the effect
React wouldn’t know what to return for the second useState Hook call. React expected that the second Hook call in this component corresponds to the persistForm effect, just like during the previous render — but it doesn’t anymore. From that point on, every next Hook call after the one we skipped would also shift by one — leading to bugs.
This is why Hooks must be called on the top level of our components. If we want to run an effect conditionally, we can put that condition inside our Hook.
2. Only Call Hooks From React Components
Don’t call Hooks from regular JavaScript functions. Instead, you can call Hooks from React function components. Let’s take look at the difference between JavaScript function and React component below:
Here we import the useState hook from the React package, and then declared our function. But this is invalid as it is not a React component.
React Function
import React, { useState} from "react";
import ReactDOM from "react-dom";
function Account(props) {
const [name, setName] = useState("Arun");
return <p>Hello, {name}! The price is <b>{props.total}</b> and the total amount is <b>{props.amount}</b></p>
}
ReactDom.render(
<Account total={20} amount={5000} />,
document.getElementById('root')
);
Even though the body of both looks similar, the latter becomes a component when we import React into the file. This is what makes it possible for us to use things like JSX and React hooks inside.
If we happened to import our preferred hook without importing React (which makes it a regular function), we will not be able to make use of the Hook we’ve imported as the Hook is accessible only in React component.
Call Hooks From Custom Hooks
A custom Hook is a JavaScript function whose name starts with use and that may call other Hooks. For example, useUserName is used below a custom Hook that calls the useState and useEffect hooks. It fetches data from an API, loops through the data, and calls setIsPresent() if the specific username it received is present in the API data.
We can then go on to reuse the functionality of this hook in other places where we need such in our application. In such places, except when needed, we don’t have to call useState or useEffect anymore.
By following this rule, we ensure that all stateful logic in a component is clearly visible from its source code.
Function Component Vs Class Component In Hooks
Let’s take a brief look at class components and functional components (with Hooks), before diving into the few Hooks best practices.
The simplest way to define a component in React is to write a JavaScript function that returns a React element:
function Welcome(props) {
return <h1>Hello, {props.name}</h1>;
}
The Welcome component accepts props which is an object that contains data and returns a React element. We can then import and render this component in another component.
The class component uses a programming methodology called Encapsulation which basically means that everything relevant to the class component will live within it. Life-cycle methods (constructors, componentDidMount(), render, and so on) give components a predictable structure.
Encapsulation is one of the fundamentals of OOP (Object-Oriented Programming). It refers to the bundling of data within the methods that operate on that data, and is used to hide the values or state of a structured data object inside a class — preventing unauthorized parties’ direct access to them.
With Hooks, the composition of a component changes from being a combination of life-cycle Hooks — to functionalities with some render at the end.
Function Component
The example below shows how custom Hooks can be used in a functional component (without showcasing what the body is). However, what it does or can do is not limited. It could be instantiating state variables, consuming contexts, subscribing the component to various side effects — or all of the above if you’re using a custom hook!
function {
useHook{...};
useHook{...};
useHook{...};
return (
...
);
}
Class Component
A class component requires you to extend from React.Component and create a render function which returns a React element. This requires more code but will also give you some benefits.
There are some benefits you get by using functional components in React:
It will get easier to separate container and presentational components because you need to think more about your component’s state if you don’t have access to setState() in your component.
Functional components are much easier to read and test because they are plain JavaScript functions without state or lifecycle-hooks.
You end up with less code.
The React team mentioned that there may be a performance boost for functional components in future React versions.
This leads to the first best practice when using React Hooks.
Hooks Best Practices
There are some best practices in writing Hooks the right and effective way as below:
Simplify Your Hooks
Organize And Structure Your Hooks
Use React Hooks Snippets
Put Hooks Rules into Consideration
1. Simplify Your Hooks
Keeping React Hooks simple will give us the power to effectively control and manipulate what goes on in a component throughout its lifetime. Avoid writing custom Hooks as much as possible; we can inline a useState() or useEffect() instead of creating our own hook.
If we find ourself making use of a bunch of custom Hooks that are related in functionality, we can create a custom hook that acts as a wrapper for these. Let’s take a look at two different functional components with hooks below.
Functional Component v1
function {
useHook(...);
useHook(...);
useHook(...);
return(
<div>...</div>
);
}
Functional Component v2
function {
useCustomHook(...);
useHook(...);
useHook(...);
return(
<div>...</div>
);
}
v2 is a better version because it keeps the hook simple and all other useHooks are inline accordingly. This allows us to create functionality that can be reused across different components and also gives us more power to control and manipulate our components effectively. Instead of adopting v1 in which our components are littered with Hooks, we should make use of v2 which will make debugging easy and our code cleaner.
2. Organize And Structure Your Hooks
One of the advantages of React Hooks is the ability to write less code that is easy to read. In some cases, the amount of useEffect() and useState() can still be confusing. When we keep our component organized it will help in readability and keep the flow of our components consistent and predictable. If our custom Hooks are too complicated, we can always break them down to sub-custom Hooks. Extract the logic of our component to custom Hooks to make our code readable.
3. Use React Hooks Snippets
React Hooks Snippets is a Visual Studio Code extension to make React Hooks easier and faster. Currently, five hooks are supported:
useState()
useEffect()
useContext()
useCallback()
useMemo()
There are two ways (Command and Extension Marketplace) we can add React Hooks snippets to our project:
4. Put Hooks Rules into Consideration
Endeavor to always put the two rules of Hooks we learned earlier into consideration while working with React Hooks.
Only call your Hooks at the top level. Don’t call Hooks inside loops, conditions or nested functions.
Always call Hooks from React function components or from custom Hooks, don’t call Hooks from regular JavaScript functions.
The ESlint plugin called eslint-plugin-react-hooks enforces these two rules, we can add this plugin to your project if we’d like it as we explain above in rules of hooks section.
Best practices have not been fully resolved because Hooks are still relatively new. So adoption should be taken with precaution one would take in adopting in any early technology. With that in mind, Hooks are the way for the future of React.
That’s all about in this article.
Conclusion
In this article, We understood about the two most important rules of React Hooks and how to effectively think in Hooks. We looked at functional components and some best practices in writing Hooks the right and effective way. As brief as the rules are, it’s important to make them our guiding compass when writing rules. If we are prone to forget it, we can make use of the ESLint plugin to enforce it.
Thanks for reading ! I hope you enjoyed and learned about the Hook Concepts in ReactJS. Reading is one thing, but the only way to master it is to do it yourself.
Please follow and subscribe us on this blog and and support us in any way possible. Also like and share the article with others for spread valuable knowledge.
If you have any comments, questions, or think I missed something, feel free to leave them below in the comment box.
Hello Readers, CoolMonkTechie heartily welcomes you in this article.
In this article, we will understand about Virtual DOM Working structure in ReactJS. We will analyse below topics to understand the Virtual DOM Concepts in ReactJS.
What is Real DOM ?
What Issues in Real DOM ?
What is Virtual DOM?
How Virtual DOM helps to solve issue?
React Elements Vs React Components in Virtual DOM
Real DOM Vs Virtual DOM
A famous quote about learning is :
” An investment in knowledge pays the best interest.”
So Let’s begin.
Real DOM
DOM stands for Document Object Model and is an abstraction of a structured text. For web developers, this text is an HTML code, and the DOM is simply called HTML DOM. Elements of HTML become nodes in the DOM.
So, while HTML is a text, the DOM is an in-memory representation of this text.
“Compare it to a process being an instance of a program. You can have multiple processes of the same one program, just like you can have multiple DOMs of the same HTML (e.g. the same page loaded on many tabs). “
The HTML DOM provides an interface (API) to traverse and modify the nodes. It contains methods like getElementById or removeChild. We usually use JavaScript language to work with the DOM, because… Well, nobody knows why :).
So, whenever we want to dynamically change the content of the web page, we modify the DOM:
#!javascript
var item = document.getElementById("myLI");
item.parentNode.removeChild(item);
document is an abstraction of the root node, while getElementById, parentNode and removeChild are methods from HTML DOM API.
Issues
The HTML DOM is always tree-structured – which is allowed by the structure of HTML document. This is cool because we can traverse trees fairly easily. Unfortunately, easily doesn’t mean quickly here.
The DOM trees are huge nowadays. Since we are more and more pushed towards dynamic web apps (Single Page Applications – SPAs), we need to modify the DOM tree incessantly and a lot. And this is a real performance and development pain.
Consider a DOM made of thousands of divs. Remember, we are modern web developers, our app is very Specific. We have lots of methods that handle events – clicks, submits, type-ins… A typical jQuery-like event handler looks like this:
find every node interested on an event
update it if necessary
Which has two problems:
It’s hard to manage. Imagine that you have to tweak an event handler. If you lost the context, you have to dive really deep into the code to even know what’s going on. Both time-consuming and bug-risky.
It’s inefficient. Do we really need to do all this findings manually? Maybe we can be smarter and tell in advance which nodes are to-be-updated?
Once again, React comes with a helping hand. The solution to problem 1 is declaratives. Instead of low-level techniques like traversing the DOM tree manually, you simple declare how a component should look like. React does the low-level job for you – the HTML DOM API methods are called under the hood. React doesn’t want you to worry about it – eventually, the component will look like it should.
But this doesn’t solve the performance issue. And this is exactly where the Virtual DOM comes into action.
Virtual DOM
In React, for every DOM object, there is a corresponding “virtual DOM object.” A virtual DOM object is a representation of a DOM object, like a lightweight copy.
A virtual DOM object has the same properties as a real DOM object, but it lacks the real thing’s power to directly change what’s on the screen.
A virtual DOM is a lightweight JavaScript object which originally is just the copy of the real DOM. It is a node tree that lists the elements, their attributes and content as Objects and their properties. React’s render function creates a node tree out of the React components. It then updates this tree in response to the mutations in the data model which is caused by various actions done by the user or by the system.
Manipulating the DOM is slow. Manipulating the virtual DOM is much faster, because nothing gets drawn onscreen. Think of manipulating the virtual DOM as editing a blueprint, as opposed to moving rooms in an actual house.
How it helps
When you render a JSX element, every single virtual DOM object gets updated.
This sounds incredibly inefficient, but the cost is insignificant because the virtual DOM can update so quickly.
Once the virtual DOM has updated, then React compares the virtual DOM with a virtual DOM snapshot that was taken right before the update.
By comparing the new virtual DOM with a pre-update version, React figures out exactly which virtual DOM objects have changed. This process is called “diffing.”
Once React knows which virtual DOM objects have changed, then React updates those objects, and only those objects, on the real DOM. In our example from earlier, React would be smart enough to rebuild your one checked-off list-item, and leave the rest of your list alone.
This makes a big difference! React can update only the necessary parts of the DOM. React’s reputation for performance comes largely from this innovation.
In summary, here’s what happens when you try to update the DOM in React:
The entire virtual DOM gets updated.
The virtual DOM gets compared to what it looked like before you updated it. React figures out which objects have changed.
The changed objects, and the changed objects only, get updated on the real DOM.
Changes on the real DOM cause the screen to change.
ReactElement Vs ReactComponent
When we are talking about the virtual DOM, it’s important to see the difference between these two.
ReactElement
This is the primary type in React. React docs say:
” A ReactElement is a light, stateless, immutable, virtual representation of a DOM Element.“
ReactElements lives in the virtual DOM. They make the basic nodes here. Their immutability makes them easy and fast to compare and update. This is the reason of great React performance.
What can be a ReactElement? Almost every HTML tag – div, table, strong.
Once defined, ReactElements can be render into the “real” DOM. This is the moment when React ceases to control the elements. They become slow, boring DOM nodes:
#!javascript
var root = React.createElement('div');
ReactDOM.render(root, document.getElementById('example'));
// If you are surprised by the fact that `render`
// comes from `ReactDOM` package, see the Post Script.
JSX compiles HTML tags to ReactElements. So this is equivalent to the above:
#!javascript
var root = <div />;
ReactDOM.render(root, document.getElementById('example'));
Once again – ReactElements are the basic items in React virtual DOM. However, they are stateless, therefore don’t seem to be very helpful for us, the programmers. We would rather work on the class-like pieces of HTML, with kind-of-variables and kind-of-constants – don’t we? And here we come to…
ReactComponent
What differs ReactComponent from ReactElement is – ReactComponents are stateful.
We usually use React.createClass method to define one:
#!javascript
var CommentBox = React.createClass({
render: function() {
return (
<div className="commentBox">
Hello, world! I am a CommentBox.
</div>
);
}
});
Your HTML-like blocks returned from render method can have a state. And the best thing is whenever the state changes, the component is re-rendered:
ReactComponents turned out to be a great tool for designing dynamic HTML. They don’t have the access to the virtual DOM, but they can be easily converted to ReactElements:
#!javascript
var element = React.createElement(MyComponent);
// or equivalently, with JSX
var element = <MyComponent />;
What makes the difference?
ReactComponents are great. They are easy to manage. But they have no access to the virtual DOM – and we would like to do as much as possible there.
Whenever a ReactComponent is changing the state, we want to make as little changes to the “real” DOM as possible. So this is how React deals with it. The ReactComponent is converted to the ReactElement. Now the ReactElement can be inserted to the virtual DOM, compared and updated fast and easily. How exactly – well, that’s the job of the diff algorithm. The point is – it’s done faster than it would be in the “regular” DOM.
When React knows the diff – it’s converted to the low-level (HTML DOM) code, which is executed in the DOM. This code is optimised per browser.
Real DOM Vs Virtual DOM
Now we can say about the difference between Real DOM and Virtual DOM that :
Real DOM is a language-neutral interface allowing programs and scripts to dynamically access and update multiple objects like content, structure, and style of a document. while Virtual DOM is a collection of modules designed to provide a declarative way to represent the DOM for an application.
The Real DOM represents the document as nodes and objects, while A virtual DOM object is a representation of a DOM object, like a lightweight copy.
Real DOM is an object-oriented representation of a web page, modified with a scripting language like JavaScript , while Virtual DOM is ideal for mobile-first applications.
Real DOM updates Slow while Virtual DOM updates faster.
Real DOM can directly update HTML, while Virtual DOM can’t directly update HTML.
Real DOM creates a new DOM if element updates, while Virtual DOM updates the JSX if element updates.
With Real DOM, DOM manipulation is very expensive, while DOM manipulation is very easy with Virtual DOM.
Real DOM includes Too much of memory wastage, while Virtual DOM includes no memory wastage.
That’s all about in this article.
Conclusion
In this article, We understood about about Virtual DOM Working structure in ReactJS.
Thanks for reading ! I hope you enjoyed and learned about the Virtual DOM concepts in ReactJS. Reading is one thing, but the only way to master it is to do it yourself.
Please follow and subscribe us on this blog and and support us in any way possible. Also like and share the article with others for spread valuable knowledge.
If you have any comments, questions, or think I missed something, feel free to leave them below in the comment box.
Hello Readers, CoolMonkTechie heartily welcomes you in A Short Note Series (Stateless Component vs Pure Component in React Application).
In this note series, we will understand about the difference between Stateless Component and Pure Component in React Application. We will be discussing how both components compare performance wise, developer experience and how both will fit into our ReactJS production project.
So Let’s Begin.
Stateless Component
STATELESS COMPONENT declared as a function that has no state and returns the same markup given the same props.
A quote from the React documentation:
” These components must not retain internal state, do not have backing instances, and do not have the component lifecycle methods. They are pure functional transforms of their input, with zero boilerplate. However, we may still specify .propTypes and .defaultProps by setting them as properties on the function, just as we would set them on an ES6 class. “
Pure Component
PURE COMPONENT is one of the most significant ways to optimize React applications. The usage of Pure Component gives a considerable increase in performance because it reduces the number of render operation in the application.
Example
Let’s look at the performance aspect of both components.
So above there is an example of a very simple Welcome Pure Component and Hello Stateless Component. When we use these two in our Parent Component, we will see Hello will re-render whenever Parent Component will re-render but Welcome Component will not.
This is because PureComponent changes the life-cycle method shouldComponentUpdate and adds some logic to automatically check whether a re-render is required for the component. This allows a PureComponent to call the method render only if it detects changes in state or props.
When to use Pure Components?
Suppose we are creating a dictionary page in which we display the meaning of all the English words starting with A. Now we can write a component which takes a word and its meaning as props and return a proper view. And suppose us using pagination to display only 10 words at a time and on scroll asking for another 10 words and updating the state of the parent component. Pure Components should be used in this case as it will avoid rendering of all the words which rendered in previous API request.
Also in cases where we want to use lifecycle methods of component then we have to use Pure components as stateless components don’t have lifecycle methods.
When to use Stateless Components?
Suppose we want to create a label with some beautiful UI which will be used to rate the credibility of a profile like BEGINNER, MODERATE, EXPERT. Since its a very small component whose re-render will hardly make any difference and creating a new component for such a small case will be time-consuming. Also if we keep making components for very small-small view, soon we will end up with so many components and it will be hard to manage when working with a big project. Also always keep in mind Pure Component comes with peculiarities of the shallowEqual.
Conclusion
In this note series, We understood about the difference between Stateless Component and Pure Component in React application.
Thanks for reading ! I hope you enjoyed and learned about the Stateless Component and Pure Component differences in React application. Reading is one thing, but the only way to master it is to do it yourself.
Please follow and subscribe to the blog and support us in any way possible. Also like and share the article with others for spread valuable knowledge.
You can find Other articles of CoolmonkTechie as below link :
Hello Readers, CoolMonkTechie heartily welcomes you in this article.
In this article, We will learn about nine useful criteria of A React Component in ReactJS. We want to know how React embraces component-based architecture. We can compose complex user interfaces from smaller pieces, take advantage of components reusability and abstracted DOM manipulations.
We know about React : “Component-based development is productive: a complex system is built from specialized and easy to manage pieces. Yet only well designed components ensure composition and reusability benefits.“
Despite the application complexity, we hurry to meet the deadlines and unexpectedly changing requirements, we must constantly walk on the thin line of architectural correctness. Make our components decoupled, focused on a single task, well tested.
Luckily, reliable components have common characteristics. We will discuss below 9 useful criterias with details.
Single responsibility
Encapsulated
Composable
Reusable
Pure or Almost Pure
Testable and Tested
Meaningful
Do Continuous Improvement
Reliability
A famous quote about learning is :
” Try to learn something about everything and everything about something.”
So Let’s begin.
When writing a React application, We need regularly ask questions ourself:
How to correctly structure the component?
At what point a big component should split into smaller components?
How to design a communication between components that prevents tight coupling?
Because Technical debt making progressively hard to modify existing or create new functionality. This will happen when write big components with many responsibilities, tightly couple components, forget about unit tests. These increase technical debt.
So we can solve this issue with the use of a reliable react component criterias. So we look these criterias one by one.
1. Single responsibility
A fundamental rule to consider when writing React components is the single responsibility principle.
” A component has a single responsibility when it has one reason to change. “
Single responsibility principle (abbreviated SRP) requires a component to have one reason to change.
A component has one reason to change when it implements one responsibility, or simpler when it does one thing.
A responsibility is either to render a list of items, or to show a date picker, or to make an HTTP request, or to draw a chart, or to lazy load an image, etc. Our component should pick only one responsibility and implement it. When we modify the way component implements its responsibility (e.g. a change to limit the number of items for render a list of items responsibility) – it has one reason to change.
Why is it important to have only one reason to change? Because component’s modification becomes isolated and under control.
Having one responsibility restricts the component size and makes it focused on one thing. A component focused on one thing is convenient to code, and later modify, reuse and test.
Let’s follow a few examples.
Example 1 :- A component fetches remote data, correspondingly it has one reason to change when fetch logic changes.
A reason to change happens when:
The server URL is modified
The response format is modified
You want to use a different HTTP requests library
Or any modification related to fetch logic only.
Example 2 :- A table component maps an array of data to a list of row components, as result having one reason to change when mapping logic changes.
A reason to change occurs when:
We have a task to limit the number of rendered row components (e.g. display up to 25 rows)
We’re asked to show a message “The list is empty” when there are no items to display
Or any modification related to mapping of array to row components only.
Does our component have many responsibilities?If the answer is yes, split the component into chunks by each individual responsibility.
An alternative reasoning about the single responsibility principle says to create the component around a clearly distinguishable axis of change. An axis of change attracts modifications of the same meaning.
In the previous 2 examples, the axis of change were fetch logic and mapping logic.
Units written at early project stage will change often until reaching the release stage. These change often components are required to be easily modifiable in isolation: a goal of the SRP.
Case study: make component have one responsibility
Imagine a component that makes an HTTP request to a specialized server to get the current weather. When data is successfully fetched, the same component uses the response to display the weather:
When dealing with alike situations, ask ourself: do we have to split the component into smaller pieces? The question is best answered by determining how component might change according to its responsibilities.
The weather component has 2 reasons to change:
Fetch logic in componentDidMount(): server URL or response format can be modified
Weather visualization in render(): the way component displays the weather can change several times
The solution is to divide <Weather> in 2 components: each having one responsibility. Let’s name the chunks <WeatherFetch> and <WeatherInfo>.
First component <WeatherFetch> is responsible for fetching the weather, extracting response data and saving it to state. It has one fetch logic reason to change:
import axios from 'axios';
// Solution: Make the component responsible only for fetching
class WeatherFetch extends Component {
constructor(props) {
super(props);
this.state = { temperature: 'N/A', windSpeed: 'N/A' };
}
render() {
const { temperature, windSpeed } = this.state;
return (
<WeatherInfo temperature={temperature} windSpeed={windSpeed} />
);
}
componentDidMount() {
axios.get('http://weather.com/api').then(function(response) {
const { current } = response.data;
this.setState({
temperature: current.temperature,
windSpeed: current.windSpeed
});
});
}
}
What benefits brings such structuring?
For instance, we would like to use async/await syntax instead of promises to get the response from server. This is a reason to change related to fetch logic:
// Reason to change: use async/await syntax
class WeatherFetch extends Component {
// ..... //
async componentDidMount() {
const response = await axios.get('http://weather.com/api');
const { current } = response.data;
this.setState({
temperature: current.temperature,
windSpeed: current.windSpeed
});
}
}
Because <WeatherFetch> has one fetch logic reason to change, any modification of this component happens in isolation. Using async/await does not affect directly the way weather is displayed.
Then <WeatherFetch> renders <WeatherInfo>. The latter is responsible only for displaying the weather, having one visual reason to change:
// Solution: Make the component responsible for displaying the weather
function WeatherInfo({ temperature, windSpeed }) {
return (
<div className="weather">
<div>Temperature: {temperature}°C</div>
<div>Wind: {windSpeed} km/h</div>
</div>
);
}
Let’s change <WeatherInfo> that instead of "Wind: 0 km/h" display "Wind: calm". That’s a reason to change related to visual display of weather:
Again, this modification of <WeatherInfo> happens in isolation and does not affect <WeatherFetch> component.
<WeatherFetch> and <WeatherInfo> have their own one responsibility. A change of one component has small effect on the other one. That’s the power of single responsibility principle: modification in isolation that affects lightly and predictability other components of the system.
2. Encapsulated
“An encapsulated component provides props to control its behavior while not exposing its internal structure. “
Coupling is a system characteristic that determines the degree of dependency between components.
Based on the degree of components dependence, 2 coupling types are distinguishable:
Loose couplinghappens when the application components have little or no knowledge about other components.
Tight coupling happens when the application components know a lot of details about each other.
Loose coupling is the goal when designing application’s structure and the relationship between components.
Loose coupling leads to the following benefits:
Allow making changes in one area of the application without affecting others
Any component can be replaced with an alternative implementation
Enables components reusability across the application, thus favoring Don’t repeat yourself principle
Independent components are easier to test, increasing the application code coverage
Contrary, a tightly coupled system looses the benefits described above. The main drawback is the difficulty to modify a component that is highly dependent on other components. Even a single modification might lead to a cascade of dependency echo modifications.
Encapsulation, or Information Hiding, is a fundamental principle of how to design components, and is the key to loose coupling.
Information hiding
A well encapsulated component hides its internal structure and provides a set of props to control its behavior.
Hiding internal structure is essential. Other components are not allowed to know or rely on the component’s internal structure or implementation details.
A React component can be functional or class based, define instance methods, setup refs, have state or use lifecycle methods. These implementation details are encapsulated within the component itself, and other components shouldn’t know anything about these details.
Units that precisely hide their internal structure are less dependent on each other. Lowering the dependency degree brings the benefits of loose coupling.
Communication
Details hiding is a restriction that isolates the component. Nevertheless, we need a way to make components communicate. So welcome the props.
Props are meant to be plain, raw data that are component’s input.
A prop is recommended to be a primitive type (e.g. string, number, boolean):
<Message text="Hello world!" modal={false} />;
When necessary use a complex data structure like objects or arrays:
To avoid breaking encapsulation, watch out the details passed through props. A parent component that sets child props should not expose any details about its internal structure. For example, it’s a bad decision to transmit using props the whole component instance or refs.
Accessing global variables is another problem that negatively affects encapsulation.
Case study: encapsulation restoration
Component’s instance and state object are implementation details encapsulated inside the component. Thus a certain way to break the encapsulation is to pass the parent instance for state management to a child component.
Let’s study such a situation.
A simple application shows a number and 2 buttons. First button increases and second button decreases the number. The application consists of two components: <App> and <Controls>.
<App> holds the state object that contains the modifiable number as a property, and renders this number:
<Controls> renders the buttons and attaches click event handlers to them. When user clicks a button, parent component state is updated (updateNumber() method) by increasing +1 or decreasing -1 the displayed number:
The first problem is <App>’s broken encapsulation, since its internal structure spreads across the application. <App> incorrectly permits <Controls> to update its state directly.
Consequently, the second problem is that <Controls> knows too many details about its parent <App>. It has access to parent instance, knows that parent is a stateful component, knows the state object structure (number property) and knows how to update the state.
The broken encapsulation couples <App> and <Controls> components.
A troublesome outcome is that <Controls> would be complicated to test and reuse. A slight modification to structure of <App> leads to cascade of modifications to <Controls> (and to alike coupled components in case of a bigger application).
The solution is to design a convenient communication interface that respects loose coupling and strong encapsulation. Let’s improve the structure and props of both components in order to restore the encapsulation.
Only the component itself should know its state structure. The state management of <App> should move from <Controls> (updateNumber() method) in the right place: <App> component.
Later, <App> is modified to provide <Controls> with props onIncrease and onDecrease. These are simple callbacks that update <App> state:
Now <Controls> receives callbacks for increasing and decreasing the number. Notice the decoupling and encapsulation restoration moment: <Controls> has no longer the need to access parent instance and modify <App> state directly.
Moreover <Controls> is transformed into a functional component:
// Solution: Use callbacks to update parent state
function Controls({ onIncrease, onDecrease }) {
return (
<div className="controls">
<button onClick={onIncrease}>Increase</button>
<button onClick={onDecrease}>Decrease</button>
</div>
);
}
<App> encapsulation is now restored. The component manages its state by itself, as it should be.
Furthermore <Controls> no longer depends on <App> implementation details. onIncrease and onDecrease prop functions are called when corresponding button is clicked, and <Controls> does not know (and should not know) what happens inside those functions.
<Controls> reusability and testability significantly increased.
The reuse of <Controls> is convenient because it requires only callbacks, without any other dependencies. Testing is also handy: just verify whether callbacks are executed on buttons click.
3. Composable
“A composable component is created from the composition of smaller specialized components.”
Composition is a way to combine components to create a bigger (composed) component. Composition is the heart of React.
Fortunately, composition is easy to understand. Take a set of small pieces, combine them, and create a bigger thing.
Let’s look at a common frontend application composition pattern. The application is composed of a header at the top, footer at the bottom, sidebar on the left and payload content in the middle:
The application demonstrates how well composition builds the application. Such organization is expressive and open for understanding.
React composes components expressively and naturally. The library uses a declarative paradigm that doesn’t suppress the expressiveness of composition. The following components render the described application:
<Application> is composed of <Header>, <Sidebar>, <Content> and <Footer>. <Sidebar> has one component <Menu>, as well as <Content> has one <Article>.
How does composition relate with single responsibility and encapsulation?
” Single responsibility principle describes how to split requirements into components, encapsulation describes how to organize these components, and composition describes how to glue the whole system back. “
Composition benefits
Single responsibility
An important aspect of composition is the ability to compose complex components from smaller specialized components. This divide and conquer approach helps an authority component conform to single responsibility principle.
Recall the previous code snippet. <Application> has the responsibility to render the header, footer, sidebar and main regions.
Makes sense to divide this responsibility into four sub-responsibilities, each of which is implemented by specialized components <Header>, <Sidebar>, <Content> and <Footer>. Later composition glues back <Application> from these specialized components.
Now comes up the benefit. Composition makes <Application> conform to single responsibility principle, by allowing its children to implement the sub-responsibilities.
Reusability
Components using composition can reuse common logic. This is the benefit of reusability.
For instance, components <Composed1> and <Composed2> share common code:
const instance1 = (
<Composed1>
/* Specific to Composed1 code... */
/* Common code... */
</Composed1>
);
const instance2 = (
<Composed2>
/* Common code... */
/* Specific to Composed2 code... */
</Composed2>
);
Since code duplication is a bad practice, how to make components reuse common code?
Firstly, encapsulate common code in a new component <Common>. Secondly, <Composed1> and <Composed2> should use composition to include <Common>, fixing code duplication:
Reusable components favor Don’t repeat yourself (DRY) principle. This beneficial practice saves efforts and time.
Flexibility
In React a composable component can control its children, usually through children prop. This leads to another benefit of flexibility.
For example, a component should render a message depending on user’s device. Use composition’s flexibility to implement this requirement:
function ByDevice({ children: { mobile, other } }) {
return Utils.isMobile() ? mobile : other;
}
<ByDevice>{{
mobile: <div>Mobile detected!</div>,
other: <div>Not a mobile device</div>
}}</ByDevice>
<ByDevice> composed component renders the message "Mobile detected!" for a mobile, and "Not a mobile device" for other devices.
Efficiency
User interfaces are composable hierarchical structures. Thus composition of components is an efficient way to construct user interfaces.
4. Reusable
“A reusable component is written once but used multiple times.”
Imagine a fantasy world where software development is mostly reinventing the wheel.
When coding, we can’t use any existing libraries or utilities. Even across the application we can’t use code that we already wrote.
In such environment, would it be possible to write an application in a reasonable amount of time? Definitely not.
Welcome reusability. Make things work, not reinvent how they work.
Reuse across application
According to Don’t repeat yourself (DRY) principle, every piece of knowledge must have a single, unambiguous, authoritative representation within a system. The principle advises to avoid repetition.
Code repetition increases complexity and maintenance efforts without adding significant value. An update of the logic forces you to modify all its clones within the application.
Repetition problem is solved with reusable components. Write once and use many times: efficient and time saving strategy.
However we don’t get reusability property for free. A component is reusable when it conforms to single responsibility principle and has correct encapsulation.
Conforming to single responsibility is essential:
“Reuse of a component actually means the reuse of its responsibility implementation.”
Components that have only one responsibility are the easiest to reuse.
But when a component incorrectly has multiple responsibilities, its reusage adds a heavy overhead. We want to reuse only one responsibility implementation, but also we get the unneeded implementation of out of place responsibilities.
We want a banana, and we get a banana, plus all the jungle with it.
Correct encapsulation creates a component that doesn’t stuck with dependencies. Hidden internal structure and focused props enable the component to fit nicely in multiple places where it’s about to be reused.
Reuse of 3rd party libraries
A regular working day. We’ve just read the task to add a new feature to the application. Before firing up the text editor, hold on for a few minutes…
There’s a big chance that the problem we start working on is already solved. Due to React’s popularity and great open source community, it worth searching for an existing solution.
Good libraries positively affect architectural decisions and advocate best practices. In my experience, the top influencers are react-router and redux.
react-router uses declarative routing to structure a Single Page Application. Associate a URL path with your component using <Route>. Then router will render the component for you when user visits the matched URL.
redux and react-redux HOC introduce unidirectional and predictable application state management. It extracts async and impure code (like HTTP requests) out of components, favoring single responsibility principle and creating pure or almost-pure components.
To be sure that a 3rd party library is worth using, here’s we need to verify checklist details:
Documentation: verify whether the library has meaningful readme.md file and detailed documentation
Tested: a sign of trustworthy library is high code coverage
Maintenance: see how often the library author creates new features, fixes bugs and generally maintains the library.
5. Pure or Almost-pure
“A pure component always renders same elements for same prop values.”
“An almost-pure component always renders same elements for same prop values, and can produce a side effect.”
In functional programming terms, a pure function always returns the same output for given the same input. Let’s see a simple pure function:
function sum(a, b) {
return a + b;
}
sum(5, 10); // => 15
For given two numbers, sum() function always returns the same sum.
A function becomes impure when it returns different output for same input. It can happen because the function relies on global state. For example:
let said = false;
function sayOnce(message) {
if (said) {
return null;
}
said = true;
return message;
}
sayOnce('Hello World!'); // => 'Hello World!'
sayOnce('Hello World!'); // => null
sayOnce('Hello World!') on first call returns 'Hello World!'.
Even when using same argument 'Hello World!', on later invocations sayOnce() returns null. That’s the sign of an impure function that relies on a global state: said variable.
sayOnce() body has a statement said = true that modifies the global state. This produces a side effect, which is another sign of impure function.
Consequently, pure functions have no side effects and don’t rely on global state. Their single source of truth are parameters. Thus pure functions are predictable and determined, are reusable and straightforward to test.
React components should benefit from pure property. Given the same prop values, a pure component (not to be confused with React.PureComponent) always renders the same elements. Let’s take a look:
function Message({ text }) {
return <div className="message">{text}</div>;
}
<Message text="Hello World!" />
// => <div class="message">Hello World</div>
You are guaranteed that <Message> for the same text prop value renders the same elements.
It’s not always possible to make a component pure. Sometimes we have to ask the environment for information, like in the following case:
<InputField> stateful component doesn’t accept any props, however renders different output depending on what user types into the input. <InputField> has to be impure, because it accesses the environment through input field.
Impure code is a necessary evil. Most of the applications require global state, network requests, local storage and alike. What we can do is isolate impure code from pure, a.k.a. apply purification on our components.
Isolated impure code explicitly shows it has side effects, or rely on global state. Being in isolation, impure code has less unpredictability effect on the rest of the system.
Let’s detail into purification examples.
Case study: purification from global variables
We don’t like global variables. They break encapsulation, create unpredictable behavior and make testing difficult.
Global variables can be used as mutable or immutable (read-only) objects.
Mutating global variables create uncontrolled behavior of components. Data is injected and modified at will, confusing reconciliation process. This is a mistake.
If we need a mutable global state, the solution is a predictable application state management. Consider using Redux.
An immutable (or read-only) usage of globals is often application’s configuration object. This object contains the site name, logged-in user name or any other configuration information.
The following statement defines a configuration object that holds the site name:
export const globalConfig = {
siteName: 'Animals in Zoo'
};
Next, <Header> component renders the header of an application, including the display of site name "Animals in Zoo":
import { globalConfig } from './config';
export default function Header({ children }) {
const heading =
globalConfig.siteName ? <h1>{globalConfig.siteName}</h1> : null;
return (
<div>
{heading}
{children}
</div>
);
}
<Header> component uses globalConfig.siteName to render site name inside a heading tag <h1>. When site name is not defined (i.e. null), the heading is not displayed.
The first to notice is that <Header> is impure. Given same value of children, the component returns different results because of globalConfig.siteName variations:
// globalConfig.siteName is 'Animals in Zoo'
<Header>Some content</Header>
// Renders:
<div>
<h1>Animals in Zoo</h1>
Some content
</div>
or
// globalConfig.siteName is `null`
<Header>Some content</Header>
// Renders:
<div>
Some content
</div>
The second problem is testing difficulties. To test how component handles null site name, we have to modify the global variable globalConfig.siteName = null manually:
import assert from 'assert';
import { shallow } from 'enzyme';
import { globalConfig } from './config';
import Header from './Header';
describe('<Header />', function() {
it('should render the heading', function() {
const wrapper = shallow(
<Header>Some content</Header>
);
assert(wrapper.contains(<h1>Animals in Zoo</h1>));
});
it('should not render the heading', function() {
// Modification of global variable:
globalConfig.siteName = null;
const wrapper = shallow(
<Header>Some content</Header>
);
assert(appWithHeading.find('h1').length === 0);
});
});
The modification of global variable globalConfig.siteName = null for sake of testing is hacky and uncomfortable. It happens because <Heading> has a tight dependency on globals.
To solve such impurities, rather than injecting globals into component’s scope, make the global variable an input of the component.
Let’s modify <Header> to accept one more prop siteName. Then wrap the component with defaultProps() higher order component (HOC) from recompose library. defaultProps() ensures fulfilling the missing props with default values:
<Header> becomes a pure functional component, and does not depend directly on globalConfig variable. The pure version is a named export: export function Header() {...}, which is useful for testing.
At the same time, the wrapped component with defaultProps({...}) sets globalConfig.siteName when siteName prop is missing. That’s the place where impure code is separated and isolated.
Let’s test the pure version of <Header> (remember to use a named import):
import assert from 'assert';
import { shallow } from 'enzyme';
import { Header } from './Header'; // Import the pure Header
describe('<Header />', function() {
it('should render the heading', function() {
const wrapper = shallow(
<Header siteName="Animals in Zoo">Some content</Header>
);
assert(wrapper.contains(<h1>Animals in Zoo</h1>));
});
it('should not render the heading', function() {
const wrapper = shallow(
<Header siteName={null}>Some content</Header>
);
assert(appWithHeading.find('h1').length === 0);
});
});
This is great. Unit testing of pure <Header> is straightforward. The test does one thing: verify whether the component renders the expected elements for a given input. No need to import, access or modify global variables, no side effects magic.
Well designed components are easy to test , which is visible in case of pure components.
6. Testable and Tested
“A tested component is verified whether it renders the expected output for a given input.“
“A testable component is easy to test. “
How to be sure that a component works as expected? We can say: “We manually verify how it works.”
If we plan to manually verify every component modification, sooner or later we’re going to skip this tedious task. Sooner or later small defects are going to make through.
That’s why is important to automate the verification of components: do unit testing. Unit tests make sure that our components are working correctly every time we make a modification.
Unit testing is not only about early bugs detection. Another important aspect is the ability to verify how well components are built architecturally.
The following statement I find especially important:
“A component that is untestable or hard to test is most likely badly designed. “
A component is hard to test because it has a lot of props, dependencies, requires mockups and access to global variables: that’s the sign of a bad design.
When the component has weak architectural design, it becomes untestable. When the component is untestable, we simply skip writing unit tests: as result it remains untested.
In conclusion, the reason why many applications are untested is incorrectly designed components. Even if we want to test such an application, we can’t.
Case study: testable means well designed
Let’s test 2 versions of <Controls> from the encapsulation point.
The following code tests <Controls> version that highly depends on the parent’s component structure:
<Controls> is complicated to test, since it relies on parent’s component implementation details.
The test scenario requires an additional component <Temp>, which emulates the parent. It permits to verify whether <Controls> modifies correctly parent’s state.
When <Controls> is independent of parent details, testing is easier. Let’s test the version with correct encapsulation:
Strong encapsulation leads to easy and straightforward testing. And contrary a component with incorrect encapsulation is difficult to test.
Testability is a practical criteria to identify how well our components are structured.
7. Meaningful
“A meaningful component is easy to understand what it does.“
It’s hard underestimate the importance of readable code. How many times did we stuck with obscured code? We see the characters, but don’t see the meaning.
Developer spends most of the time reading and understanding code, than actually writing it. Coding activity is 75% of time understanding code, 20% of time modifying existing code and only 5% writing new source.
A slight additional time spent on readability reduces the understanding time for teammates and ourself in the future. The naming practice becomes important when the application grows, because understanding efforts increase with volume of code.
Reading meaningful code is easy. Nevertheless writing meaningfully requires clean code practices and constant effort to express ourself clearly.
Component naming
Pascal case
Component name is a concatenation of one or more words (mostly nouns) in pascal case. For instance <DatePicker>, <GridItem>, <Application>, <Header>.
Specialization
The more specialized a component is, the more words its name might contain.
A component named <HeaderMenu> suggests a menu in the header. A name <SidebarMenuItem> indicates a menu item located in sidebar.
A component is easy to understand when the name meaningfully implies the intent. To make this happen, often we have to use verbose names. That’s fine: more verbose is better than less clear.
Suppose we navigate some project files and identify 2 components: <Authors> and <AuthorsList>. Based on names only, can we conclude the difference between them? Most likely not.
To get the details, you have to open <Authors> source file and explore the code. After doing that, we realize that <Authors> fetches authors list from server and renders <AuthorsList> presentational component.
A more specialized name instead of <Authors> doesn’t create this situation. Better names are <FetchAuthors>, <AuthorsContainer> or <AuthorsPage>.
One word – one concept
A word represents a concept. For example, a collection of rendered items concept is represented by list word.
Pick one word per concept, then keep the relation consistent within the whole application. The result is a predicable mental mapping of words – concepts that you get used to.
Readability suffers when the same concept is represented by many words. For example, we define a component that renders a list of orders <OrdersList>, and another that renders a list of expenses <ExpensesTable>.
The same concept of a collection of rendered items is represented by 2 different words: list and table. There’s no reason to use different words for the same concept. It adds confusion and breaks consistency in naming.
Name the components <OrdersList> and <ExpensesList> (using list word) or <OrdersTable> and <ExpensesTable> (using table word). Use whatever word we feel is better, just keep it consistent.
Code comments
Meaningful names for components, methods and variables are enough for making the code readable. Thus, comments are mostly redundant.
Case study: write self-explanatory code
Common misuse of comments is explanation of inexpressive and obscured naming. Let’s see such case:
// <Games> renders a list of games
// "data" prop contains a list of game data
function Games({ data }) {
// display up to 10 first games
const data1 = data.slice(0, 10);
// Map data1 to <Game> component
// "list" has an array of <Game> components
const list = data1.map(function(v) {
// "v" has game data
return <Game key={v.id} name={v.name} />;
});
return <ul>{list}</ul>;
}
<Games
data=[{ id: 1, name: 'Mario' }, { id: 2, name: 'Doom' }]
/>
Comments in the above example clarify obscured code. <Games>, data, data1, v, magic number 10 are inexpressive and difficult to understand.
If we refactor the component to have meaningful props and variables, the comments are easily omitted:
Don’t explain ourself with comments. Write code that is self-explanatory and self-documenting.
Expressiveness stairs
We distinguish 4 expressiveness stairs of a component. The lower we move on the stairs, the more effort we need to understand the component.
We can understand what the component does from:
Reading name and props;
Consulting documentation;
Exploring the code;
Asking the author.
If name and props give enough information to integrate the component into application, that’s a solid expressiveness. Try to keep this high quality level.
Some components have complex logic, and even a good name can’t give the necessary details. It’s fine to consult the documentation.
If documentation is missing or doesn’t answer all the questions, We have to explore the code. Not the best option because of additional time spent, but it’s acceptable.
When exploring code doesn’t help decipher the component, the next step is asking component’s author for details. That’s definitely bad naming, and avoid going down to this step. Better ask the author to refactor the code, or refactor it yourself.
8. Do continuous improvement
“We then said that rewriting is the essence of writing. We pointed out that professional writers rewrite their sentences over and over and then rewrite what they have rewritten.”
To produce a quality text, we have to rewrite our sentence multiple times. Read the written, simplify confusing places, use more synonyms, remove clutter words – then repeat until we have an enjoyable piece of text.
Interestingly that the same concept of rewriting applies to designing the components.
Sometimes it’s hardly possible to create the right components structure at the first attempt. It happens because:
A tight deadline doesn’t allow spending enough time on system design
The initially chosen approach appears to be wrong
We’ve just found an open source library that solves the problem better
or any other reason.
Finding the right organization is a series of trials and reviews. The more complex a component is, the more often it requires verification and refactoring.
Does the component implement a single responsibility, is it well encapsulated, is it enough tested? If we can’t answer a certain yes, determine the weak part (by comparing against presented above 9 attributes) and refactor the component.
Pragmatically, development is a never stopping process of reviewing previous decisions and making improvements.
9. Reliability
Taking care of component’s quality requires effort and periodical review. It worth investment, since correct components are the foundation of a well designed system. Such system is easy to maintain and grow with complexity that increases linearly.
As result, development is relatively convenient at any project stage.
On the other hand, as system size increases, we might forget to plan and regularly correct the structure, decrease coupling. A naive approach to just make it work.
But after an inevitable moment when system becomes enough tightly coupled, fulfilling new requirements becomes exponentially complicated. We can’t control the code, the weakness of system controls us. A bug fix creates new bugs, a code update requires a cascade of related modifications.
How does the sad story end? We might throw away the current system and rewrite the code from scratch, or most likely continue eating the cactus. We’ve eaten plenty of cactuses, we’ve probably too, and it’s not the best feeling.
The solution is simple, yet demanding: write reliable components.
That’s all about in this article.
Conclusion
In this article, We understood about nine useful criteria of A React Component in ReactJS. The presented 9 characteristics suggest the same idea from different angles :
“A reliable component implements one responsibility, hides its internal structure and provides effective set of props to control its behavior.”
Single responsibility and encapsulation are the base of a solid design. We conclude that :
Single responsibility suggests to create a component that implements only one responsibility and has one reason to change.
Encapsulated component hides its internal structure and implementation details, and defines props to control the behavior and output.
Compositionstructures big and authority components. Just split them into smaller chunks, then use composition to glue the whole back, making complex simple.
Reusable components are the result of a well designed system. Reuse the code whenever you can to avoid repetition.
Side effects like network requests or global variables make components depend on environment. Make them pure by returning same output for same prop values.
Meaningfulcomponent naming and expressive code are the key to readability. Your code must be understandable and welcoming to read.
Testing is not only an automated way of detecting bugs. If you find a component difficult to test, most likely it’s incorrectly designed.
A quality, extensible and maintainable, thus successful application stands on shoulders of reliable components.
What principles do you find useful when writing React components?
Thanks for reading ! I hope you enjoyed and learned about the nine useful criteria of A React Component in ReactJS. Reading is one thing, but the only way to master it is to do it yourself.
Please follow and subscribe us on this blog and and support us in any way possible. Also like and share the article with others for spread valuable knowledge.
If you have any comments, questions, or think I missed something, feel free to leave them below in the comment box.