React JS ❤️ Javascript
A review of some of the main Javascript features that React JS uses regularly
Whenever they ask me why I like React so much, one of the reasons I give is that when we work with this library along the way we reinforce and expand our knowledge of Javascript: there are no special functions (as for example in Angular) to perform tasks such as paint a list of items or call an API but everything is native. This means that if ReactJS someday loses its position as the most popular library for frontend development, our work will not have been wasted, as we will have learned many Javascript concepts along the way.
In this article I have proposed to collect some of the features and functions of Javascript that are used intensively when we develop with React. So if you are starting, you will have a guide to know what you need to know about Javascript to feel comfortable with React.
Let’s get started!
The && operator to paint elements conditionally
The &&
and ||
they work in a special way in Javascript because they behave like short circuits. This means that its result is not always a Boolean as in other languages, but what we will obtain will be one of the elements that is operating.
Specifically, the &&
operator has two characteristics:
- It is evaluated from left to right.
- If the first operand evaluates to false the second operator is not evaluated.
console.log("Cat" && "Dog"); // 'Dog'
console.log(false && "Dog"); // false
This operator is often used in React to paint components conditionally. Suppose you want to paint a component only when a condition is met. Thanks to the && operator, this behavior is very easy to implement, and best of all, it is pure Javascript:
function Bar() { const condition = false; return ( <div> {/* Este elemento no se renderizará */} {condition && <Foo />} </div> );}
The map function to paint lists of items
Another Javascript function that is used repeatedly is the Array.prototype.map
method that allows us to iterate over a list of elements and apply an individual operation to each one of them.
const arr = [1, 2, 3];const doubled = arr.map(n => n * 2); // [2, 4, 6]
This method is especially useful when we have to paint lists of elements in React, since we can use it within the JSX of our component to iterate the list and return each element wrapped in the component that we want:
const products = ['iPhone', 'iPad', 'Apple Watch'];function Products() { return ( <ul> {products.map(product => <li key={`product--${product}`}> {product}</li>)} </ul> );}
By the way. You may be wondering why we use the key attribute in lists of items similar to the previous example. Here is a link to an article that I published so you know why:
The arrow functions
If you have noticed, in the previous example to the map
method we are passing a function expressed as “arrow function”. This shorter syntax is very useful when we use it within JSX, since it allows us to express the iteration over the elements in a much shorter way (in addition to not using an extra pair of keys, the code is more readable):
const products = ['iPhone', 'iPad', 'Apple Watch'];function Products() { return ( <ul> {products.map(function(product) {
return (<li key={`product--${product}`}>{product}</li>);
})} </ul> );}
In addition, during the days when components were still defined using classes, the “arrow functions” allowed us to save ourselves the odd scare with the variable this
(at the same time that we saved ourselves having to bind the this
variable in each method that was going to be used as “event listener”):
// Sin arrow function
class AwesomeComponent extends React.Component{
constructor( props ){
super( props );
this.onClick = this.onClick.bind(this);
}
onClick(event){
// ...
}
render(){
return (
<button type="button"
onClick={this.onClick}>
Click
</button>
);
}
}
// Con arrow function
class AwesomeComponent extends React.Component{
onClick = (event) => {
// ...
}
render(){
return (
<button type="button"
onClick={this.onClick}>
Click
</button>
);
}
}
If you are interested, you can read more about this “problem” in the following article:
Object Destructuring
Another feature that Javascript offers us and that we repeatedly work with in React is the destructuring of objects, which allows us to assign their properties directly to variables:
const person = {id: 1, name: 'Gerardo'};
const {id, name, telephone = 'default telephone'} = person;
console.log(id); // 1
console.log(telephone); // 'default telephone'
Destructuring is common when we work with the properties of the components:
function Button({onClick, text}) {
...
}
Of course this technique can also be applied to arrays:
const lunch = ['🍝', '🥩', '🍎', '☕'];
const [firstCourse] = lunch;
console.log(firstCourse); // '🍝'
Something that surely sounds familiar to you because it is the way we usually work with the React useState hook:
const [count, setCount] = useState(0);
ES Modules
Another feature that Javascript provides us with are the modules, thanks to the import-export syntax that allows us to “bring” functionality declared in other files to use within ours.
At this point it is sure that you are not surprised to find this line:
import React, {useState} from 'react';
In addition, for a long time Javascript also supports the dynamic import of modules, something that React takes advantage of to allow us to bring components asynchronously and thus reduce the size of the main bundle. To do this, simply use the lazy instruction to wrap the import:
const FooComponent = React.lazy(() => import('./foo'))
And use the Suspense
component to display a loading message while the FooComponent
module is retrieved asynchronously:
import {Suspense} from 'react';function Bar() {
return (
<Suspense fallback="Cargando...">
<FooComponent />
</Suspense>
);
}
🧙🏼♂️ Trick
Remember that if you want to work with absolute imports in your application, you just have to create a jsconfig.json
file in the root of the project with the following content:
{
"compilerOptions": {
"baseUrl": "src"
}
}
Which will allow you to go from importing like this:
import {HOME_PATH} from '../../../config/router/paths';
to import like this:
import {HOME_PATH} from 'config/router/paths'
Much more comfortable, right?
Backticks
Another feature that ES6 incorporated at the time and that is very useful when working with React is the backtick.
Thanks to them, concatenating text strings and variables is written in a much more readable way:
const name = 'Gerardo';
const surname = 'Fernández';
const telephone = '123 123 123';// "Old syntax"const userInfo = 'User info: ' + name + ' ' + surname + ' ' + telephone;// "New syntax"const userInfo = `User info: ${name} ${surname} ${telephone}`;
This syntax is common to find in the JSX of our components, because thanks to it we can write sentences like the following:
function CounterView({counter}) {
return (<div>{`Valor del contador: ${counter}`}</div>);
}
I think the improvement is evident!
In addition, back quotes have another series of advantages that I summarized in the following article so that you can see their full potential:
Chaining operator
One of the most recent incorporations that we have received in Javascript is the “chaining operator” which allows us to access the properties of the objects safely, without worrying about whether along the way we will find an undefined
that causes a failure:
const person = {
name: 'Gerardo',
email: 'mail@mail.com'
}console.log(person.currentJob.title);// Uncaught TypeError: Cannot read property 'title' of undefined
Thanks to the “chaining operator” we can access properties that we are not sure if they exist and it will take care of returning undefined instead of throwing an error:
const jobTitle = person?.currentJob?.title; // undefined
This in React is very useful if, for example, we are retrieving objects from an API whose properties are not always listed, helping us to prevent possible failures.
Promesas and fetch
Finally, in a compilation of Javascript utilities that are used in React, neither the promises nor of course the fetch function to make calls to external APIs could be missing:
import React, {useEffect, useState} from 'react';
function MyComponent() {
const [users, setUsers] = useState(null);
useEffect(async function() {
const response = await fetch('https://reqres.in/api/users');
const json = await response.json();
setUsers(json.data);
});
if (!users) {
return <div>Todavía no hay usuarios</div>;
}
return (
<ul>
{users.map(user => <li key={`user--${user.id}`}>{user.first_name}</li>)}
</ul>
);
}
Again React squeezing Javascript to the maximum to implement functionality using the capabilities of the language.
Final thoughts
As you have seen with all the examples I have mentioned, React in the end is just a library located on top of Javascript to help us develop our applications much faster but at all times we are resorting to the characteristics of the language to implement our functionality.
For me, this is what really differentiates React from other libraries: feeling that you go hand in hand with language and that everything you learn today will surely serve you for the future even if our favorite library disappears.