All The Javascript Concepts You Need To Know Before Learning React (Part 2)
Tags: webdev, javascript, beginners, react
Published: 2024-07-04 10:12:05

After a short break, thorough understanding, and countless hours of thinking. Here is the continuation of [All The Javascript Concepts You Need To Know Before Learning React (Part 1)](https://dev.to/up_min_sparcs/all-the-javascript-concepts-you-need-to-know-before-learning-react-part-1-3if5) article I made a while ago. These concepts will act as a bridge towards learning React. Without further ado, let's delve into this article.

## 6. Understanding DOM 

The Document Object Model, or DOM for short, is the representation of a web page. It has a tree-like structure where each node represents an individual HTML element. The DOM can be manipulated using JavaScript to create dynamic content and change or add elements, attributes, and styles. Performance-wise, direct DOM manipulation can be a problem, especially for complex applications, as you need to grab the nodes and apply changes to them manually, and the browser needs to re-render frequently, causing inefficiency and difficulty in managing. 


![Example of DOM](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/64bfzrz5zwlf0eun17z4.jpg)

### Virtual DOM

React has its own kind of DOM called Virtual DOM, which is a virtual representation of UI that is synced with the "real" DOM. Virtual DOM finds the minimal set of changes needed to update the real DOM. This approach reduces the number of re-renders and improves efficiency. 

> You don't need to understand everything fully, but this gives you an idea of why React is popular

## 7. Async Await and Promises

Normally, everything is synchronous when you code in Javascript, meaning the execution is line by line. 

```js
let message = "Hello World";
console.log(message);
```

> The first line of code is executed, declaring and initializing the message variable, and when it is done, the next line will print the message in the terminal or console.

But sometimes, there is a need for non-synchronous activity. Fetching from API is a common example of this. Fetching data from API may not always be instantaneous. Factors involving your internet connection, the size of your request, and how far you are from the server come into play.

```js
const picturesOfCats = fetch("https://api.thecatapi.com/v1/images/search?limit=5")
console.log(picturesOfCats);
```

> Also, that is a real API for getting data about cats :> Check out [The Cat API](https://thecatapi.com/). Not sponsored btw.


![The Cat API](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jmkxgxt5umawlmuyh0xl.png)


Here, we are fetching pictures of cats from an API and attempting to print those data. However, we will encounter something strange.


![Running the code](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tm91uarzziqpjrr0u5pt.png)


This is the result of `console.log(picturesOfCats);`. So what is this `Promise { <pending> }`? 

### Promises

Promises in JavaScript are objects used to deal with asynchronous operations. They represent a value that may be available now, in the future, or never. 

```js
const myPromise = new Promise((resolve, reject) => {
  const success = true; // Simulate success or failure

  if (success) {
    resolve("The operation was successful!"); // Call resolve if the operation is successful
  } else {
    reject("The operation failed."); // Call reject if the operation fails
  }
});
```
In this very simplistic example, we have a variable containing a promise.
This `Promise` will take on a function with two arguments: resolve and reject. And inside the function, we can write logic to define this `Promise`.

> If you are confused, that's okay. Most of the time, we will not create our own promises. We will just use promises that are returned and deal with them.

`resolve` is a function we call if the promise is successful, while the `reject` is a function we call if the promise is unsuccessful. But how do we determine what `resolve` and `reject` are?

```js
myPromise.then((result) => {
    console.log(result); // Handle the successful result
}).catch((error) => {
    console.error(error); // Handle the error
});
```
We will use the `.then()` and `.catch()` for those. `.then()` is a function that will be called if we're resolved, and `.catch` is a function that will be called if we're rejected. If the promise is resolved, we will see `"The operation was successful!"` that came from the `result` variable that was passed from the `resolve()` and if not, we will see `"The operation failed."` that came from the `error` variable that was passed from the `reject()`.

> When making API requests, we will only use `.then()` and `.catch()` most of the time, meaning when the request is made, `.then()` we will do something, and if there are errors in the request, then we are going to `.catch()` that errors.

There is also a `finally` case where it will be called regardless of whether the promise is resolved or rejected.

```js
myPromise.then((result) => {
    console.log(result); // Handle the successful result
}).catch((error) => {
    console.error(error); // Handle the error
}).finally(() => {
    console.log("Promise Finished") // Will be called regardless if resolve or reject
});
```

Returning to the code that results in `Promise { <pending> }`. Fetching data from API is asynchronous, but the program is synchronous, so the pending promise is getting printed because the fetch returns a `Promise` instead of the actual data.

### Fetching Data

```js
const fetchCatPictures = () => {
  const picturesOfCats = fetch("https://api.thecatapi.com/v1/images/search?limit=5")
  picturesOfCats
    .then(response => {
      return response.json()
    })
    .then(data => {
      console.log(data); // log the data when the Promise resolves
    })
    .catch(error => {
      console.error("Error fetching data:", error); // handle any errors
    }).finally(() => {
      console.log("This is the end of the request");
    });
};

// Call the function
fetchCatPictures();
```

Here is an example of fetching data from an API. Here, if the promise is resolved successfully, it returns a `Response` object. This `Response` object represents the HTTP response from the server. To extract meaningful data from this response, we need to parse it using the `json()` method.

### Async + Await

There is actually a different approach for fetching and waiting data, which uses `async` + `await`, which allows JavaScript to wait for asynchronous operations to complete sequentially.

```js
const fetchCatPictures = async () => {
  try {
    const response = await fetch("https://api.thecatapi.com/v1/images/search?limit=5");
    const data = await response.json();
    console.log(data); // log the data when the Promise resolves
  } catch (error) {
    console.error("Error fetching data:", error); // handle any errors
  } finally {
    console.log("This is the end of the request");
  }
};

// Call the async function
fetchCatPictures();
```

In this code snippet, we convert the code that uses `.then()` with `async` + `await`. `async` is used to declare asynchronous functions which return promises. It also allows `await` keyword to be used inside that function. `await` is used to pause the execution of an `async ` function until a Promise is settled.

> Basically, `async` is needed to use `await`. Also, `await`
waits for the fetch to be done, then we can do something with the data after.

To handle errors when fetching data, we use the `try-catch` block, and for the `.finally(),` we just replace it with `finally.`

> In a `try-catch` block, we basically try some codes, and if there are errors, then those will be caught by the `catch`.

Both `.then()` method chaining and `async` + `await` are fundamentally the same because `async` + `await` is syntactic sugar that simplifies working with promises. This syntax allows for a more synchronous style of writing asynchronous code, which enhances readability. Both approaches are equally valid for handling asynchronous operations in JavaScript.

### Other Ways Of Fetching Data From API

There are many ways to fetch data from an API. We can use the `fetch()` like the codes above or use Javascript libraries such as Axios.

First, you need to install Axios if you haven't already. You can do this using npm or yarn:

```bash
npm install axios
```
or with yarn:

```bash
yarn add axios
```

> Make sure you add `"type": "module"` in your `package.json` or if you don't have one, you can put `.mjs` on your file instead of `.js`.

```js
const axios = require("axios"); // Import Axios (use `import axios from "axios"` if using ES modules)

const fetchCatPictures = async () => {
  try {
    const response = await axios.get("https://api.thecatapi.com/v1/images/search?limit=5");
    console.log("Data fetched successfully:", response.data);
  } catch (error) {
    console.error("Error fetching data:", error);
  }
};

// Call the async function
fetchCatPictures();
```

> Note: The new way of importing in Javascript uses the `import` keyword, just like in my previous article. But the old way `require` can still be used. For more info, check out this [article](https://blog.logrocket.com/commonjs-vs-es-modules-node-js/).

> Also, Axios offers numerous features, including direct access to the data property from the response, which is already parsed as a JSON object. This eliminates the need for manually invoking `.json()`, making data handling more convenient.

## 8. Optional Chaining

The optional chaining `?.` operator prevents errors when trying to access properties or call methods on `null` or `undefined` values. If a reference is `null` or `undefined`, the expression will return `undefined` instead of throwing an error. When used with function calls, it returns `undefined` if the specified function does not exist.

```js
const student = {
    name: "Mark",
    age: 19,
    address: {
        city: "Davao City",
        country: "Philippines"
    }
}

const studentSchool = student.school?.name;
console.log(studentSchool); // Expected output: undefined 

console.log(student.someNonExistentMethod?.()); // Expected output: undefined
```

In this example, we are trying to get the values of nonexistent property and method, which will throw an error, but with the optional chaining `?.` operator, it will only result in an undefined value.

In React or even plain Javascript, when fetching and dealing with data, sometimes your app can break when you are not specific with the data you are receiving or dealing with. Similarly above, if you are trying to access fields inside objects where those fields don't exist, your application will break.

```js
const fetchData = async () => {
    const data = await fetch("exampleapi.com");
    const name = data.student?.name
}
```

Here, assuming we are fetching data from an imaginary API, and `student` property may or may not exist. We can prevent breaking our app by using optional chaining `?.` operator. This ensures safely accessing properties and calling methods on objects that may have nullish values.

> The optional chaining `?.` operator also helps to simplify code because there is no need for verbose conditional checks (`if` statements or ternary `?` operators).

## 9. Template Literals

Template literals are very useful, especially in React. They are string literals that allow embedded expressions and multiline strings. They are enclosed by backticks instead of single or double quotes, making creating complex strings with dynamic content easier.

>  It seems I cannot show backticks in this platform as backticks are reserved for markup, but they are usually located below the Esc Key.

```js
const fetchData = async (animalName) => {
    const data = await fetch("exampleapi.com/searchitem=" + animalName);
};
```

In this simple code snippet, assuming that we can add a search term, we can do something like this where we concatenate the API link with the argument containing our desired `animalName` using `+` operator. The API can send back pictures of animals or, in this case, cats.

```js
const fetchData = async (animalName) => {
    const data = await fetch(`exampleapi.com/searchitem=${animalName}`);
};
```
However, we can also use a template literal by replacing the quotes with backticks and adding `${}`. This makes it much more readable and easier to manage, especially when constructing complex strings with dynamic content.

> Basically, you can now add Javascript inside your strings :>

I hope you were able to grasp the concepts of both my articles. This article is a little bit shorter than the first, but it still contains important concepts for you to learn. With this, you will have an advantage when transitioning from Javascript to React. Before I conclude this article, I would like to show an inspiring quote from my references.

> Sometimes, overpreparing will hold you down and prevent you from actually progressing.

Just learn the essentials and don't delve too deep, as JavaScript and React are two separate coding experiences.

Happy Coding!

> I will probably delve into backend soon. Anyways, thanks for reading! 

---

References:
https://www.youtube.com/watch?v=ACaT1Gfhe6I