On this page:
React is written in JavaScript (JS), and not just any JS, modern JS.
At React GraphQL Academy the thing that we often see students struggling with most is understanding the syntax of modern JS and applying it correctly in the context of React, often times what may seem like an "Understanding React issue" is actually a misconception about JS. So let’s take a look at the essential JS features all React devs should know.
First up, there’s more than one way to refer to JavaScript! When people say "ES5, ES6, ES7 etc" they are referring to a standard called ECMAScript which JavaScript is based on. Why the weird name? It’s a long story involving the Swiss, let’s move on as it’s not important 😆
The important thing to know is that ES6 is the addition number and ECMAScript 2015
is the specification. So just to confuse things you may hear people refer to it either way but the most common way is to use the addition number.
Basically it was a very big update when it was released, between 2009 and 2015 there was not much change in the language. After ES6 the language is now being incrementally updated every year so we have ES7, ES8, ES9 (currently). The subsequent updates though are much smaller so the vast majority of things you need to be familiar with were things that became standardized with ES6:
ES5 < 2015 (from 2009)
ES6 = 2015
ES7 = 2016 (small update)
ES8 = 2017
ES9 = 2018
ESNEXT > 2018
What is ESNEXT? It’s the future, everything that is not in a current release and is a proposal (at whatever stage) is referred to as ESNEXT.
What version should React developers use??
Babel is a transpiler for JavaScript. This means going from one version of the language to another version (unlike a compiler where you change language). We use babel as JavaScript is an evolving language, not all of the newest updates are supported, both by browsers (client-side) and node (server-side). If you’d like to understand how babel works and watch it work it’s magic, check out this quick session: https://github.com/reactgraphqlacademy/babel-exercise#babel-exercise
You see the point? If you didn’t do it no problem as this is normally a configuration step and is done for you if you are using create- react-app to spin up a React project. However, we do recommend understanding how it works as babel is an essential piece of the mix for React apps:
In older JavaScript when we declared a new variable we used var. ES6 introduced two new ways to declare variables, let and const.
The two key reasons that it’s good to use these new variable declarations are:
Simply put, scope is where something is available. In the example above where is c available? Inside the { } This is a block. What about if we used var here? Then c would be available in the global scope. It’s also important to remember that JavaScript is function scoped, meaning is there was a function in the code above and we used var, it’d be available inside that function.
This feature is great as it stops our variables "leaking" into the global scope.
Two things to bear in mind:
If you are declaring a variable and are not going to mutate it, use const. Otherwise use let. This is the standard usage in an up-to-date React project.
The console will throw an error if you mutate const. That said, const is not fully immutable (like in other languages) since you can declare an array with const and then mutate that array by using array.prototype.push for example, so you should be aware of this. When declaring a variable with const you are signalling you are not planning on mutating it (hence the name), in JS we don’t have out of the box immutability so we are responsible for that!
There are three main advantages to arrow functions:
An implicit return means you don’t have to write the return keyword:
In this example we are using the implicit return in the function passed to array.prototype.map
You could also do this:
If you are writing an inner function or declaring a variable inside your function you’ll want to take this approach. This is why the implicit return is also known as a one-liner syntax as generally you’ll use it on one line to make the code more concise.
Probably the most important thing to know about arrow functions is that they get their binding from the context. This means their
this
value is going to point to whoever is the caller. We recommend looking at this example to help understand this:
https://jsbin.com/caxuceg/edit?html,js,console
Also, we previously wrote a more in-depth article on arrow functions, I do recommend it 😉
JavaScript: The beauty of arrow functions
Destructuring allows us to extract values from arrays and objects and store them in variables with a more convenient syntax.
You can destructure arrays:
And also objects:
The most important thing to remember when first getting started is that everything to the left of the
is destructuring syntax and everything to the right is the object or array being destructured. So in the example above, we assign two variables, leanjs and reactgraphqlacademy from the object at the nested point of apiData.links.websites=
So the values of those newly declared variables will be equal to the values of the key’s (the two urls). Another way of declaring and assigning the variable leanjs would be:
const leanjs = apiData.links.websites.leanjs
This is a convenient way to assign variables. With ES6 we can also assign variables in this way directly inside function parameters if you know the keys of the object passed in, this is very common in React:
You can assign default values to function parameters using "=", for example:
const getArea = (x=400, y=500) => x*y
Try it out here: https://jsbin.com/kederum/3/edit?js,console
We can rename variables when destructuring using ":" and assign a new name. At React GraphQL Academy we like to ask people this head scratcher that combines a few of these concepts togther:
const { w: width = 400, h: height = 500 } = { w: 800 }
What are the variables and what are their values here?
Have a look for yourself if you’re struggling: https://jsbin.com/kederum/7/edit?js,console
In reality you’re not likely to see code like this as it’s confusing (not a great quality for code), but it’s interesting to think about what’s going on and why 🤔
This allows us to "spread" a set of values from a data structure inside another data structure:
In this case we have declared a new array called
allLanguages
which is the result of spreading the values of languages
and dsl
. This is incredibly useful for helping us to avoid mutations, and it works the same way with objects, consider the following:
By using spread on line 8 we avoid mutating. Why is this useful? In a nutshell state mutations make it incredibly hard to keep track of values at a given time, we recommend reading what the React docs say on the power of not mutating data.
The rest operator has similar syntax to spread but does the opposite. It allows us to pass an indefinite amount of arguments:
In this example we are doing some array destructuring, what value do you think additionalInfo is?
It’s an array of the REST of the values
When used with destructuring, the rest operator will scope up the rest of the values. The rest operator must of course always be used last, otherwise we could simply assign the values.
Here’s an example of how we commonly use the rest operator in React along with some destructuring in the parameters:
There are two very important points to bear in mind with classes in JS.
Why was this introduced? Basically to make JS more approachable to developers from and object oriented background. Classes were at the time of the ES6 release and are still currently a somewhat contentious topic in JS as they are obfuscating what’s actually happening.
Consider the following code:
This should look familiar if you’ve used an OOP language before. We have a constructor which is called upon instantiation of the class, we can write class variables, and we can define class methods. Simple stuff I hope 😎
However, be aware that what’s happening under the hood in JS is this:
As the MDN docs point out:
"When it comes to inheritance, JavaScript only has one construct: objects. Each object has a private property which holds a link to another object called its."
If you wanted to extend a class, you can now do this also with the class syntax as you can imagine. However, we won’t delve into that here as when using React, you should never use inheritance beyond extending
React.Component
On that note, have you ever heard the phrase favour composition over inheritance? Well, react is all about composition.
If you’d like to get started writing React components using the class syntax, check out our article on thinking in react and it’s exercise repo.
Template literals, also called "string literals" are a great new way to use strings in our JS. Let’s consider the old way we used to do things:
animal.name + ‘is a’ + animal.species
Can you spot the error in the above code? There is a spacing issue! And that’s not something immediately obvious which demonstrates just how error prone this way of concatenating strings was. Now we can do this:
`${animal.name} is a ${animal.species}`
The key thing to know is that now we can use
``
(back ticks) to create a string and then everything inside the ${ }
is JavaScript. This is incredibly useful as we can do things like this:
The other key features of template literals are:
Models are something that those coming from other languages should already be very familiar with. In JS they were only introduced in ES6 making them quite new! Modules help us to make our code more organized and easier to reason about. It also means that we are able to isolate our code by easily creating different scopes.
Before modules we used to do things like this:
Why? Here we are using the fact that JS is function scoped and writing and immediately invoked function in order to ensure that variables do not leak into the global scope. If this doesn’t make sense to you, no problem! Now we have modules so you won’t be using it!
Just as in other languages modules can be imported and exported, and there are a few ways of expressing these depending on the use case.
When exporting, the most common thing to do is create a default export. This should be done at the bottom of your file and when working with React will be the way you export your components:
Sometimes you may want to export multiple values from a modules, a good example of this is a utils file.
In this case you can either write the keyword export in-front of the function(s):
export function sumTwo(a, b) { return a + b }
Alternatively you can declare your functions and export them at the bottom of the file with the named export syntax:
export { sumTwo, sumThree }
When importing there are a few different options and we need to think about what exacty we want to import, is it the whole module? Is it a names export?
The most common case is importing the default export, in this case the name that we give the import does not actually matter, however it’s best not to change it to avoid confusion, so if you’re importing MyComponent then you should maintain the same name 😉
Here are all the options:
import test from './test';
'./math';
import { sumTwo, sumThree } from './math';
import { sumTwo as addTwoNumbers, sumThree as sumThreeNumbers } from 'math/addition';
import * as util from './math';
const { sumTwo, sumThree } = util;
import React, { Component } from 'react';
What is a promise? Simply put, a promise is something that will happen in the future but maybe not immediately. It’s a way to help us handle asynchronous code such as network calls.
The most important thing you’ll need to do as a React developer is understand how to consume promises, why? Because when you call an api it’s going to return a promise. The easy way to know that something is a promise is that you can call .then() on it.
So you may do something like this:
So what’s happening here? First up we call an API using fetch (check out the link). That call returns a promise which we can call
then()
on. We then parse the response to json and that returns another promise where we can then extract the session. If something goes wrong, we use catch()
to handle the error. You’ll need to be comfortable with consuming promises as a React developer so take your time and don’t forget to consult the docs: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise
So how do I write my own promise?
Promises are global functions in modern JS and can be declared like this:
New Promise((resolve, reject) => { … resolve() or reject() })
In the case of an API, in the resolve you would return the data itself and in the reject you would return an error object with a status. You probably won’t have to write your own promises but it’s worth understanding how to, as you will be working with them a lot.
A new feature was added in ES8 which builds on top of the idea of promises called async await. This builds on top of promises and you can refactor in either direction, so it’s important to first understand the concept of promises before using this alternative syntax.
Of course there are many more features in ES6 that were not covered here. This article does not aim to be exhaustive, but rather give you a good idea about what we consider to be the most important ES6 features you must know to use React well. When we see people struggling with JS on one of our intensive react developer training 99% of the time it’s something that was covered here. Of course, in order to get familiar with the language the only way is to practice! We recommend trying out some of these exercises to expand your understanding of ES6.
Looking forward to seeing you soon in a meetup or training ;-)
We won't spam you as per our Privacy Policy.
Share this on:
Comments? Shoot me a tweet @reactgqlacademy !
GraphQL Evening with Round Table 💥 Online
London, UK
Prices & more details