Review of Essential JavaScript for React - vonschappler/Ultimate-React GitHub Wiki

Destructuring arrays and objects

Destructuring is useful when we are working with one or more objects that contains multiple attributes or arrays.

Let's see a how would be a code be writen without and with destructyring an object:

Without destructuring
const book = getBook(2);
const title = book.title;
const author = book.author;
const pages = book.pages;
const genres = book.genres;
// and this would continue for each property form the book object
With destructuring
const book = getBook(2)
const {title, author, pages, <attribues...>} = book

NOTE:

When destructuring an array, the name of the attribute inside the {} need to match the name used during the definition of the object to destructure.

When destructuring an array, it's important to notice that instead of relying on the attribute name, destructuring relies on the number of items / index of the item to retrieve.

const pGenre = genres[0];
const sGenre = genres[1];
// and this would continue for each genre inside the genres array
With destructuring
const [pGenre, sGenre, <attribues...>] = genres

NOTE:

The names given (pGenre, sGenre, etc.) will assing the values in the order the items are inside the array (genre[0], genre[1], and so on).

The code for this lesson can be found here.


Rest/Spread operator

The rest operator ... is used to create an additional array which contains all elements in a arrya which were not defined inside a destructured array definition. It's always defined at the end of the destructured definition, as displayed below

const [pGenre, sGenre, ...other] = genres;

The spread operator is also defined by the ..., but this one can be used on both arrays and objects, as exemplified below:

Spread used with arrays
const newGenres = [...genres, 'epic fantasy'];
Spread used with arrays
// Creates a new array called newGenres with the item 'epic fantasy' as it last element
const newGenresA = [...genres, 'epic fantasy'];

// Creates a new array called newGenres with the item 'epic fantasy' as it first element
const newGenresB = ['epic fantasy', ...genres];

The placemet of the spread operator is important, because it'll define the postioning of the items added to the new array created

Spread used with objects
const updatedBook = { book, moviePublicationDate: '2001-12-19', pages: 1210 };

When it comes to objects, the spread operator is useful to add new properties to an existing objects or create a new property to them. When overwriting values of properties of objetcs, the spread object needs to come first.

The code for this lesson can be found here.


Literals

Literals (``) are part of the features added to ES6. This allows to add JavaScript variables or operations inside a string.

To add any Javascript variable or oparation inside a literal, we use ${} to create the JavaScript block which will contain the variable or literal inside the literal template started with the backtick.

const affirmation = `${title} is a book!`;

The code for this lesson can be found here.


Ternaries

Ternaries are operations with 3 operators: a condition, the result if the condition is satisfied and the result if it's not.

The syntax for this operation is displayed in the example below:

pages > 1000 ? '' : ' ';

The code for this lesson can be found here.


Arrow Functions (aka expression functions)

Arrow functions is a new way of writing quick and "one line" functions. Those are used mostly as callback functions and in most cases it's advised to store them into a variable.

An example of an arrow function can be seen on the code below:

// with blocks - requires the return keyword at the end of the block
const getYearBlock = (str) => {
  const year = str.split('-')[0];
  return year;
};

// without blocks
const getYearNoBlock = (str) => str.split('-')[0];

The code for this lesson can be found here.


Logical operators and short-circuiting

And operator

The And operator (&&) short-circuits when the condition checked as the first argument is false, automatically returning the the fisrt argument as a result.

// No short-circtuing
// prints 'It was true' on the console, while returning the string on the sencond argument as a value
console.log(true && 'It was true');

// Short-circuiting
// prints 'false' on the console, while returning the boolean false as a value, ignoring the second argument
console.log(false && 'It was not true');

// it works with truthy and falsy values also
// prints 'Yes a do have a name!' on the console, while returning the string on the sencond argument as a value
console.log('name' && 'Yes a do have a name!');
// prints 'null' on the console, while returning null as value
console.log(null && 'I do not have a nickname...');

Or operator

The Or operator (||) short-circuits when the condition checked as the first argument is true, automatically returning the the fisrt argument as a result. This is mostly used to define default values.

// Short-circtuing
// prints 'true' on the console, while returning it as a value
console.log(true || 'It was true');

// No short-circuiting
// prints 'false' on the console, while returning the boolean false as a value, ignoring the second argument
console.log(false || 'It was not true');

// it works with truthy and falsy values also - except the falsy 0
// prints 'name' on the console, while returning 'name' as a value
console.log('name' || 'Yes a do have a name!');
// prints 'I do not have a nickname' on the console, while returning it as value
console.log(null && 'I do not have a nickname...');

Nullish coalescing operator

The Nullish coalescing operator (??) short-circuits when the condition checked as the first argument is true, automatically returning the the fisrt argument as a result. This is mostly used to define default values. This works as a substitute of || for the falsy values null and undefined, returing everything else as value, no matter the value provided as fisrt argument.

// prints '0' on the console, while returning 0 as a value
console.log(0 ?? 'It is a 0 value');

// prints 'null' on the console, while returning null as a value, ignoring the second argument
console.log(null ?? 'Is it null?');

The code for this lesson can be found here.


Optional Chaining

Optional Chaining declarations (?) exist in order to specify to our JavaScript code to continue chaining properties from an object only if the previous one was found for the object in question. This is usefull if we are unsure about the existence of a property provided on from a data or an objcet to prevent returning undefined as a value while, simultaneously, setting a default value in case that property does not exist.

const person1 = {
  name: 'Alex',
  surname: 'Crimsom',
};
const greeting1 = `Hello ${person1.name} ${
  person1.surname
}! Is your full name ${person1?.fullName ?? 'Joe No One'}?`;
// Because the object person has no property "fullName" and there is the ?? operand here to set the default value to 'Joe No One', the console will print the message:
// 'Hello Alex Crimsom! Is your full name Joe No One?'
console.log(greeting1);

const person2 = {
  name: 'Alex',
  surname: 'Crimsom',
  fullName: 'Alex Paul Crimsom',
};
const greeting2 = `Hello ${person2.name} ${
  person2.surname
}! Is your full name ${person2?.fullName ?? 'Joe No One'}?`;
// Because the object person now has the property "fullName" the console will print the message:
// 'Hello Alex Crimsom! Is your full name Alex Paul Crimsom?'
console.log(greeting2);

The code for this lesson can be found here.


Array map

The map method will loop through an array and as a result it will return a new array with the same length of the original array, with some operation applied to EACH element of the original array.

The map mathod always expect a callback function inside it, just like the exemple below.

const numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
const multiplyByTwo = numbers.map((el) => el * 2);
// This will print the array [0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20] on the console.
console.log(multiplyByTwo);

The code for this lesson can be found here.


Array filter

The filter method will loop through an array and as a result it will return a new array with the elements that match the filter condition specified inside the callback function expected by the filter array method.

const numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
const filter = numbers.filter((el) => el * 2 >= 10);
// This will print the array [5, 6, 7, 8, 9, 10] on the console.
console.log(filter);

The code for this lesson can be found here.


Array reduce

The reduce method "reduces" the original array to a single value by executing the callback function provided with it on it's declaration. It basically loops through the array adding the current array value to the value returned (also know as accumulator - by convention defined as acc inside the callback function) on the previous calculation.

The second argument provided is the initial value of the accumulator and it's optional. If that value is not provided, it will default to the first element of the original array.

The sintaxe of the reduce method is displayed on the example below.

const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
const factor = numbers.reduce((acc, el) => el * acc, 1);
// This will print the the value 3628800 on the console.
console.log(factor);

The code for this lesson can be found here.


Array Sort

The sort method, the the name says, will sort an array, organizing it's elements, by default, in ascended order by converting them into strings and comparing their UTF-16 code values, mutating the original array.

There is a small trick which can be done to prevent this mutation by adding the method slice() - which will create a copy of the original array - and chaining it to the sort method afterwards.

If a callback function is provided, it will compare the elements base on the rules/calculations made by the callback function.

A basic example of how sort number sintaxe of the sort method is displayed on the example below.

const numbers = [3, 7, 10, 9, 6, 1];
const sortAsc = numbers.slice().sort();
const sortDesc = numbers.slice().sort((a, b) => b - a);
// This will print the the value [1, 3, 6, 7, 9, 10] on the console.
console.log(sortAsc);
// This will print the the value [10, 9, 7, 6, 3, 1] on the console.
console.log(sortDesc);
// This will print the original array, without any sorting, because the method slice was used before both sorting methods above
console.log(numbers);

The code for this lesson can be found here.


Immutable Arrays

The simplest way of working with immutable arrays is applying our operations (add, delete, update, etc) to a new array, using the knowledge acquired in the previous classes. Examples of how to do it, are listed below.

Adding elements to an Array

const numbers = [0, 1, 2, 3, 4];
const newNumbers = [...numbers, 5];
// This will print on the console the array [0, 1, 2, 3, 4, 5]
console.log(newNumbers);

Deleting elements from an Array

const numbers = [0, 1, 2, 3, 4, 5];
const newNumbers = numbers.filter((el) => el !== 3);
// This wil print on the console the array [0, 1, 2, 4, 5]
console.log(newNumbers);

Updating elements from an Array

const numbers = [0, 1, 2, 3, 4, 5];
const newNumbers = numbers.map((el) => (el == 3 ? (el = 6) : el));
// This wil print on the console the array [0, 1, 2, 6, 4, 5]
console.log(newNumbers);

The code for this lesson can be found here.


Promises

In browsers, in order to get data from a external source/API, we usually mae use of the method fetch(), which requires as a parameter the URL of the source we wish to request data from.

This will return what we call a Promise, which need to be treated on the code. Promises can be into at least 3 basic 3 states:

  • Pending - the promise is collecing data and waiting for the the next stage (uses then() with a callback function to either Reject or Resolve the promise)
  • Rejected - the promise failed to colect the data or execute the next stage (uses catch() with a callback function to handle any errors)
  • Fullfiled/Resolved - the promise was successfuly executed

The example below is a short recipe on how to work with Promises:

const API_URL = 'anyurl';
fetch(API_URL)
  .then((res) => res.json())
  .then((data) => console.log(data))
  .catch(console.log('Some error handler message or function...'));

The code for this lesson can be found here.


Async/Await

A simple way to work with promises using the async/away way of hadling them is represented on the code below:

const API_URL = 'anyurl';
async function getData() {
  const res = await fetch(API_URL);
  const data = await res.json();
  return data;
}
const myData = await getData();
console.log(myData);

The code for this lesson can be found here.

⚠️ **GitHub.com Fallback** ⚠️