Befriending Javascript...

Before the internet, life was very different than today. Although few things remained the same then and now, eating (food), sleeping, etc. But, Before the internet, there was nothing such as digital, the only forms of communication were physical or vocal. Back then, you had to step out of the house to socialize.

Source: D K Joinery/Twitter

The above diagram illustrated how life was before the internet applications, service providers took over.

Henceforth before the Internet people were more somatic than virtual. All this changed slowly but rapidly after the Internet revolution, and people started eating more. Tada! not eating food but eating content, consuming services, etc.

Internet & Web

Internet is the combination of both hardware and software intertwined. There is a vast infrastructure that goes behind the hardware of the Internet. The cabling and the external wiring are levied in a specific pattern emerging as the Internet source. There's a fab website that tells about how this all is carried.

Submarine Cable Map

The only entry points of Internet sources in India are Mumbai, Cochin, Chennai, Trivandrum, and Tuticorin.

Now coming to the Web is the only way to access information online. According to the books, the Web is a system of Internet servers that support specially formatted documents. The documents are formatted in a markup language called HTML, or Hypertext Markup Language, which supports several features, including links and multimedia. In addition, these documents are interlinked using hypertext links and are accessible via the Internet.

But! But! But!

Yes, I am not moving away from the context like Anand from KGF 😅😅😅

PS: KGF Chapter 1

The creation of the Web started the relevance of the Internet and JavaScript approximately 30 years ago when the first ever web page was gone live. However, the Web is incomplete without JavaScript. Let's look into some examples of web pages with JavaScript disabled.

  1. Netflix doesn't load anything except the logo.
Netflix loses its plot without Javascript 😅

2. G-mail without JavaScript

Gmail mails a disclaimer

Hence, from the above example World Wide Web, aka Web without JavaScript, is like a plant 🪴 in a dark room with no water💧, sunlight ☀️, or space to breathe and live. Similarly, the Web without JavaScript is a read-only page with no user interactions, data, or functionalities.

Javascript: The Rise

Human lives today are dependent on the interactivity JavaScript provides. The above section has described how the web looks without JavaScript.We are, to a reasonable degree, dependent on JavaScript to function.

Today, virtually every computing device, including iPhones, Android phones, macOS, Windows, Linux, smart TVs, etc., has JavaScript interpreters installed on them and in active use. Currently, there are 1.8 billion websites worldwide, and 95% of them use JavaScript. The following is an illustration of the facts.

Const Javascript

As you can see from the above, How many ever languages come over the next years Javascript is like "Main Jhukega Nai"

Javascript crossing the path with Pushparaj 😎

Javascript: The Rule

Let's understand how to rule the web in this section using Javascript and move closer to the objective of this blog.

The world is growing rapidly through tech and slowly moving towards the Digital spectrum. In this race of automation, new tools, libraries, and frameworks are being released almost every fortnight. Through this rapid change, there has been a bit of ignorance towards the language, especially in the younger part of the community. Although, it's necessary to adapt to the latest libraries, and frameworks it's more necessary to understand the language first. Language is evergreen and is like the foundation pillars of a building. How much ever the structure, amenities, and interiors of the building keep changing, the foundations laid over will be constant.

The objective of this blog post is to understand JavaScript in a better way through the help of a small application. Presenting the WindBnb, an application developed in pure JavaScript and CSS/SCSS without using any frameworks/library to understand the hidden concepts that are abstracted while using a framework/library but learning them might make you better in the journey.

0:00
/
GitHub - AssSam7/devc-windbnb: This application is a challenge created by Devchallenges to scaffold a simple hotel viewing app similar to Airbnb.
This application is a challenge created by Devchallenges to scaffold a simple hotel viewing app similar to Airbnb. - GitHub - AssSam7/devc-windbnb: This application is a challenge created by Devcha...
GitHub Repo
WindBnb | DevC
Live URL

Design Analogy 🔖

The design is the core of any application that can form an inflection in the development process. A proper design symmetry eases the whole process of the project. As the design philosophy of the application was desktop-first, it required an approach with minimal costs in the style changes and additions. As most of the application is dynamic, the style management needed to be optimized so as not to take a toll on the performance.

CSS3 be like

It has all the features required for this approach, and the few left are taken care of by its pre-processor SASS. CSS concepts like grid, flex and responsive units are majorly a part of the design language. The layout is held using the grid system as that helps in the viewport scalability. The flexbox is the best choice for internal elements like cards, drawers, etc. Finally, responsive units like rem, vw, and vh add to the overall acoustics of the design.

De-ciphering the Markup

The application's markup is written to be easily tailored and accessed through Javascript. The BEM class notation is followed in the markup. There are three main parts of BEM.

  1. The block holds everything (elements) inside and acts as a scope.
  2. The element acts as a specific part of the component. It should be prefixed with the block name, and followed by two underscores. Eg: head__eye, header__nose, etc.
  3. Modifier which adds additional styles to a specific element(s). It should be prefixed with either the block or the element name, and two hyphens. Eg: head__eye—left, head__eye—right, etc.

This sums up the acronym BEM. Let’s understand this better below. Following are the sections inside the markup.

Note: The whole markup of the application is inside a wrapper div with the class container.

  1. Header Section

Block

  1. header element with the class header

Elements

  1. div with the class header__logo
  2. div with the class header__search
  3. div with the class search__city
  4. div with the class search__guests
  5. div with the class search__icon

Modifiers - None

Header Section 

2. Header Overlay Section

Block

  1. div with the class overlay

Elements

  1. div with the class overlay__close
  2. div with the class overlay__search
  3. div with the class btn__search

Modifiers

  1. div with the class overlay__close—icon
  2. div with the class btn__search—icon
Overlay Header Section

3. Main Section (Here, Javascript will inject the HTML dynamically)

Block

  1. div with the class stay

Elements

  1. div with the class stay__img
  2. div with the class stay__details
  3. div with the class stay__title

Modifiers

None

Main Section

Architecture

WindBnb Architecture (High Level)

After the initial baby steps of designing the application, the next phase in the same section is architecting the application. The application's architecture helps to understand many crucial parts of the app. Although Javascript has no features to follow MVC/MVT, they can be implemented explicitly. WindBnb follows the MVC pattern where a central controller directs the whole application between the Model (data) and views (UI elements). It also follows the 7-in-1 architecture of the SASS with partials and main files.

Understanding the Modular Structure

Folder Structure of the Application

Explaining some of the essential files

appController.js

Here is the application's entry point and the single control source for the whole application. The following are some of the important jobs of this file.

  • Creating the instance to the Model class, passing the mock data as the argument, and storing the instance.
  • Creating the instance to the App View class and passing the stored model instance.
  • Implementing & Controlling the Search Functionality.

appModel.js

Here is the model layer of the application. The following are the jobs carried out by this file.

  • Receiving the Mock Data and storing it in the internal data structure.
  • Util methods related to the data alteration related to filtering.

appView.js

Here is the root view component of the application. The following are some of the essential jobs carried out by this file.

  • Creating the instance of the individual view classes, and passing the model instance received from the controller.
  • Selecting and Storing the references to the DOM elements.
  • Adding the event listeners and performing individual user actions.
  • Initializing & Processing the search functionality and rendering the search data.
  • Injecting the dynamic HTML to the DOM as per the use case.

Frameworks behind the scene and comparison with JavaScript

Frameworks and Libraries come with plenty of features that can rapidly improve the speed of development. Although, using a framework or library can be like constructing a building by integrating many blocks, not necessarily knowing each block individually. Following are some of the discussion points of language vs. framework/library. The scope of discussion of this blog is only restricted to React.

  1. Deep dive into JSX

Let's take a small code snippet from the WindBnb. The objective of the following function is pretty straightforward, i.e., accepting two arguments and returning the markup as a string.

Javascript Similar to JSX

Now, let's create a React functional component for the same use case. The following component's objective is the same as the above Javascript function.

React Functional Component

We can draw the following observations from the above.

  1. Both Javascript function and React functional component are very similar syntactically.
  2. The Javascript function accepts arguments individually, but React component takes arguments/props as an object that can be de-structured.
  3. In the React functional component, className is used instead of class in JSX because the class is a JavaScript keyword, and xlinkHref is used instead of xlink:href as SVG tags should be written in camelCase.
Javascript Function & React Functional Component Side-by-Side

Let's tweak the Javascript function and rewrite the same functionality in the DOM way. The following is the DOM structure for the above markup.

  1. Stay Details Container Node (Root)
  2. Stay Category Container Node
  3. Super Host Text Node
  4. Stay Type Text Node
  5. Stay Rating Container Node
  6. Star SVG Node
  7. Stay Rating Text Node

The above structure can be visualized as the below tree diagram that represents the DOM tree

DOM Tree

Let's create a Javascript function replicating the above DOM structure.

Javascript Similar to JSX Behind the Scenes
  • document.createElement() is used to create a DOM node and takes one argument i.e., the tagName, and returns a new element. It also takes a second argument that is out of the scope of this blog post.
  • Element.className is used to assign the classes to the element.
  • Element.textContent is used to assign the text content to the element.
  • Element.appendChild() is used to append the child node to the parent element/node.

Let's understand the previously written React JSX and how it works under the hood. Computers don't understand anything else except the machine language that gives instructions in 0's and 1's, and browsers also understand only HTML, CSS, and Javascript but not JSX. Behind the scenes, Babel does the job and compiles the JSX to React.createElement()calls, where each JSX element is just syntactic sugar for calling React.createElement(). Let's look into an example to understand this better by developing the same use case. The following is also known as React without JSX.

React Old JSX (JSX Behind the Scenes)

Let's briefly talk about the arguments of React.createElement().

  • The first argument is to specify the tagName. This argument is the same as the first and mandatory argument of the document.createElement().
  • A second argument is an object that contains props specific to this element.
  • Finally, the last argument is the children of this component, like the nested elements of this component.

Now, let's look into them side-by-side to understand the concept better.

Javascript React Original JSX Behind-the-Scenes

Key Points of Comparison:

  1. From the above comparison, it can be drawn that the left Javascript code snippet is similar to a React Functional Component.
  2. In React, you won't be using document.createElement(). However, React  React.createElement() is similar to document.createElement() but there are also differences.
  3. document.createElement() returns a DOM element (for example a div or an h1). Whereas React.createElement() returns an object that represents the DOM element.

Let’s see how these returns values look like

document.createElement()

const h1 = document.createElement('h1');
console.log(h1);

The above code returns

React.createElement()

const h1 = React.createElement("h1", {}, "Hello World");
console.log(h1);

The above code returns

As the library's job is to simplify the tasks, React.createElement() simplifies the task of creating the element, and configuring everything in a single line. Whereas document.createElement() typically needs 2-3 lines, one for making the element, another for setting the props, and the next to append the part.

2. Classy Coding

ECMA Script 2015 (ES6) introduced a new way of writing Javascript code using the Classes, providing a better way to follow object-oriented patterns. Let’s understand the classes in this section. Classes, especially in Front end community have become like Bajaj Chetak these days which gets spotted so rarely these days as people moved to Hero, Suzuki, and TVs respectively.

People with Chetak these days 😆😅😅

Similarly, in the Tech space developers have moved on to the Functional programming pattern. In React, Classes were used extensively till 2018 when hooks got introduced. In 2022, Classes are not React's way of creating components anymore but knowing them adds to the core of being a web developer. Let's try to understand them below.

Re-creating the same class in React is a little easy as the libraries' job is to make things easy.

Following are the essential tasks of the component.

  • The constructor receives the props and manages the state of the component.
  • Events are handled in the following way
class App extends React.Component {
	constructor(props) {
		...
		...
		this.handleHeaderSearch = this.handleHeaderSearch.bind(this);
	}

	handleHeaderSearch() {
		...
		...
		...
	}

	render() {
		return (
			...
			<div class="header__search margin-sm" onClick={handleHeaderSearch}>
                 <h2 className="search__city">Where do you travel?</h2>
                 <h2 className="search__guests">Add guests</h2>
                 <svg className="search__icon">
                   <use xlinkHref="assets/sprites.svg#icon-search">					   </use>
                 </svg>
      	    </div>
			...
		);
	}
}
What is This

Why is binding required? Confused, will understand after this part

Only a single render method is responsible for rendering the component. (Refer to above code)

Dependency injection is handled from outside the component in a below way

(index.js) 
import App from './App';

const rootElement = document.getElementById("root");
ReactDOM.render(<App data={...} cities={[...]} />, rootElement);

Why do we bind This?

While working on React, you must have come across controlled components and event handlers. We need to bind these methods to the component instance using .bind() in our custom component’s constructor like how we have done in the above example.

Let’s try to understand, Why is that required?

Let’s see what happens if we do not bind the event handler method with its component instance in the below example.

class SampleThis extends React.Component{
  constructor( props ){
    super( props );
  }
    
  handleClick(event){
    console.log(this); // 'this' is undefined
  }
    
  render(){
    return (
      <button type="button" onClick={this.handleClick}>
        Click Me
      </button>
    );
  }
}

ReactDOM.render(
  <SampleThis />,
  document.getElementById("app")
);
This is undefined 🥲

Let’s try to understand this undefined behavior

This has nothing to do with React, and the answer to this behavior lies in How Javascript is. The “this” in Javascript refers to the current object from where it’s being called. Understanding this with a few more examples below

Default Binding

function display(){
 console.log(this); // 'this' will point to the global object
}

display();

This is a native function call. The value of this inside the display() method, in this case, is the window — or the global — object in non-strict mode. In strict mode, this value is undefined.

Implicit Binding

Now, putting the same function inside an object makes it behave like this

var obj = {
	name: 'Rahul',
	display: function() {
		console.log(this.name); // 'this' here will point to the 'obj'
	}
};

obj.display(); // Rahul

As discussed before, this differs in the way where it’s being called. In the first example, the display() function was called directly, hence it referred to the global object. In the second example, the display() function was put inside an object and was called using that object. Hence, now this pointed to that object.

Again Again

Again the catch here is, Suppose we assign this function reference to another variable and invoke the function using this new function reference, we get a different value of this inside display()

var name = "global again!!!";
var outerDisplay = obj.display;
outerDisplay(); // global again!!!

This is how the behaviour of this changes from use case to use case. In this case, the value of this inside display()falls back to default binding*.* It points to the global object or undefined if the function being invoked uses strict mode. This is especially applicable while passing such functions as callbacks to another custom function, a third-party library function, or a built-in JavaScript function like setTimeout that takes callbacks as arguments.

Yep! That's how it works!

Hell Yes!!! That’s the sole reason why we need to bind this in the class components when passing the event handlers as the callbacks from outside. As we observed in the React Component example,  this value was undefined as the context was lost after passing the handler as a callback.

Wait a sec, Shouldn’t this point to the global object in that case?

Answer: No! Because

The bodies of class declarations and class expressions are executed in strict mode, that is the constructor, static, and prototype methods. Getter and setter functions are executed in strict mode.

You can read the full article about the same here.

So, to prevent this, we need to bind  this  value like this:

class SampleThis {
  constructor(name){
    this.name = name
    this.display = this.display.bind(this);
  }

  display(){
    console.log(this.name);
  }
}

var foo = new Foo('Rahul');
foo.display(); // Rahul

var display = foo.display;
display(); // Rahul

3. Doodling the DOM

DOM stands for Document Object Model. HTML is the language of web pages. It provides the web page structure with many specialized tags, including the way to link multiple pages together. The structure of a web page is represented as a tree structure document object. The JavaScript programming language can change the structure of this document object to bring dynamic behavior to the web pages. The DOM(Document Object Model) is the programming interface for the tree structure web page documents. The document tree is called the DOM Tree.

Now let's see if there’s a paragraph and if we have to change the text of the paragraph(the <p> tag), we will need the ability to find the <p>tag from the document tree and then set a new text value to it. We have to do all these using the JavaScript DOM APIs.

const paragraph = document.querySelector("p");
paragraph.innerText = 'Some other text!';

The mechanism of finding a particular node in the document tree is called Querying the DOM. Adding a new node, deleting a node, or updating a node in the document tree is called DOM Manipulation. The result of a DOM manipulation reflects on the web user interface. This process is called rendering.

A few ways of Querying the DOM are

  • [document.querySelector](<https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelector>)(selector)
  • [document.querySelectorAll](<https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelectorAll>)(name)
  • [document.createElement](<https://developer.mozilla.org/en-US/docs/Web/API/Document/createElement>)(name)
  • element.[innerHTML](<https://developer.mozilla.org/en-US/docs/Web/API/Element/innerHTML>)

Now the equivalent of the document.querySelector() the method in React is using refs. To select an element, set the ref prop on it to the return value of calling the useRef() hook and access the dom element using the current property on the ref, e.g. ref.current.

How does React handle DOM?

React is a library that has a few layers of abstraction from the original DOM API. It provides something known  refs for accessing the DOM in this abstract way. In the real DOM, every time even changing inner text on that wee tiny <p> tag means having to re-render the whole Document!

As revisited many times in this blog libraries, and frameworks bring a lot of add-on things to the table simplifying the process. But, understanding the underlying concepts makes it, even more, simpler and a better developer. So, React works with a Virtual DOM. It keeps a track of changes in its own Virtual DOM before ‘mounting’ to the old school DOM in the way it deems most efficient.

useRef

useRef is a hook that returns an object with a current property set to the value passed to the hook.

For instance this:

const numberRef = useRef(0);
// numberRef is initialised as an object with a current property

Would return an object like so:

{current: 0};
// numberRef.current holds the value 0

It also provides a way for developers to interact directly with DOM nodes, outside of React’s management of the Virtual DOM. React describes this as an “escape hatch”.

We can use the ref attribute of React elements to set the **current** property to be the actual DOM node the element is rendered to. This way we can use the reference for old-school DOM manipulation adding event listeners etc.

const divRef = useRef();
/* divRef is initialised with current property set to 'undefined' because we didn’t give a value to the hook.*/

const MyComponent = (props) => {
  return <divref={divRef}> A Div! </div>;
};

/* by passing divRef to the ref={} attribute, when the component is mounted to the DOM the divRef.current property gets set to the actual DOM node, eg. "<div>A Div!</div>" */

Can we use Old school Javascript DOM API in React?

Apparently, we can use the vanilla javascript DOM API in React as well because React eventually is just Javascript right?

But, will you ever use it when you have useRef?

Yes, there are some instances when you can’t refer to the elements i.e. selecting the element is not possible.

The following example of this polymorphism

Accessing Javascript DOM in React FC

Output:

How Similar are they
As from the above, both are like twins to each other internally.

Through WindBnb, now that you have climbed Mt. Everest, developing the same using a framework would be like climbing Mt. Fuji that would reduce the effort and ease the process by ten folds as observed in the above section.

Success!!!

Conclusion

Javascript is here to stay, it's not gonna go anywhere at least not any soon. Although, frameworks and libraries can change, come and go Javascript remains constant. Learning Javascript, especially when pursuing a career in the web is imperative. Hence, creating a real-time application in Javascript first helps a lot in understanding the core concepts better. Following are some of the concepts you need to know before getting into React.

  • Callback functions
  • Imports, Exports (Default, Named), and ES6 modules
  • Map(), Filter(), and Find() methods
  • Destructuring arrays and objects
  • Rest and Spread operators
  • Optional chaining
  • Arrow Functions
  • Asynchronous Programming

Thinking of becoming a React developer, I would recommend you to become a Javascript developer first which eventually makes you a better React/Angular/Vue dev more precisely a better Front end developer.

Want more insights and expert tips? Don't just read about Javascript! Work with brilliant engineers at Codemonk and experience it's effective use case firsthand!


Credits

A big shout out to the devchallenges.io platform and the creator of it Thu Nghiem. WindBnb is a part of a challenge in the front-end developer roadmap. Kudos to the platform, for the idea, and the UI/UX design.