DEV Community

Cover image for All The Javascript Concepts You Need To Know Before Learning React (Part 2)
Mark Jaily Peña for UP Mindanao SPARCS

Posted on • Edited on

All The Javascript Concepts You Need To Know Before Learning React (Part 2)

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) 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

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.

let message = "Hello World";
console.log(message);
Enter fullscreen mode Exit fullscreen mode

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.

const picturesOfCats = fetch("https://api.thecatapi.com/v1/images/search?limit=5")
console.log(picturesOfCats);
Enter fullscreen mode Exit fullscreen mode

Also, that is a real API for getting data about cats :> Check out The Cat API. Not sponsored btw.

The Cat API

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

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.

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
  }
});
Enter fullscreen mode Exit fullscreen mode

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?

myPromise.then((result) => {
    console.log(result); // Handle the successful result
}).catch((error) => {
    console.error(error); // Handle the error
});
Enter fullscreen mode Exit fullscreen mode

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.

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
});
Enter fullscreen mode Exit fullscreen mode

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

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();
Enter fullscreen mode Exit fullscreen mode

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.

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();
Enter fullscreen mode Exit fullscreen mode

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:

npm install axios
Enter fullscreen mode Exit fullscreen mode

or with yarn:

yarn add axios
Enter fullscreen mode Exit fullscreen mode

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.

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();
Enter fullscreen mode Exit fullscreen mode

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.

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.

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
Enter fullscreen mode Exit fullscreen mode

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.

const fetchData = async () => {
    const data = await fetch("exampleapi.com");
    const name = data.student?.name
}
Enter fullscreen mode Exit fullscreen mode

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.

const fetchData = async (animalName) => {
    const data = await fetch("exampleapi.com/searchitem=" + animalName);
};
Enter fullscreen mode Exit fullscreen mode

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.

const fetchData = async (animalName) => {
    const data = await fetch(`exampleapi.com/searchitem=${animalName}`);
};
Enter fullscreen mode Exit fullscreen mode

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

Top comments (0)