Quick Look at JS in React
Entering React after learning JavaScript
When you enter the world of React, you are often confronted with a React Class Component:
In a React class component, there are lots of things to digest for beginners which are not necessarily React: class statements, class methods and inheritance due to being a class. Also JavaScript import statements are only adding complexity when learning React. Even though the main focus point should be JSX (React’s syntax) – everything in the return statement – in the very beginning, often all the things around demand explanations as well. This article is supposed to shed some light into all the things around, most of it JavaScript, without worrying too much about React.
React and JavaScript Classes
Being confronted with a React class component, requires the prior knowledge about JavaScript classes. One would assume that this is given knowledge, but it isn’t, because JavaScript classes are fairly new in the language. Previously, there was only JavaScript’s prototype chain which has been used for inheritance too. JavaScript classes build up on top of the prototypical inheritance giving the whole thing a simpler representation with syntactic sugar.
In order to understand JavaScript classes, you can take some time learning about them without React:
A class describes an entity which is used as a blueprint to create an instance of this entity. Once an instance of the class gets created with the new
statement, the constructor of the class is called which instantiates the instance of the class. Therefore, a class can have properties which are usually located in its constructor. In addition, class methods (e.g. getName()
) are used to read (or write) data of the instance. The instance of the class is represented as the this
object within the class, but outside the instance is just assigned to a JavaScript variable.
Usually classes are used for inheritance in object-oriented programming. They are used for the same in JavaScript whereas the extends
statement can be used to inherit with one class from another class. The more specialized class inherits all the abilities from the more general class with the extends
statement, and can add its specialized abilities to it:
Basically that’s all it needs to fully understand React class components. A JavaScript class is used for defining a React component, but as you can see, the React component is only a “React component” because it inherits all the abilities from the actual React Component
class which is imported from the React package:
That’s why the render()
method is mandatory in React class components: The React Component from the imported React package instructs you to use it for displaying something in the browser. Furthermore, without extending from the React Component, you wouldn’t be able to use other lifecycle methods. For instance, there wouldn’t be a componentDidMount()
lifecycle method, because the component would be an instance of a vanilla JavaScript class. And not only the lifecycle methods would go away, React’s API methods such as this.setState()
for local state management wouldn’t be available as well.
However, as you have seen, using a JavaScript class is beneficial for extending the general class with your specialized behavior. Thus you can introduce your own class methods or properties.
Now you know why React uses JavaScript classes for defining React class components. They are used when you need access to React’s API (lifecycle methods, this.state
and this.setState()
). In the following, you will see how React components can be defined in a different way without using a JavaScript class.
After all, JavaScript classes welcome one using inheritance in React, which isn’t a desired outcome for React, because React favors composition over inheritance. So the only class you should extend from your React components should be the official React Component.
Arrow Functions in React
When teaching someone about React, I explain JavaScript arrow functions pretty early. They are one of JavaScript’s language additions in ES6 which pushed JavaScript forward in functional programming.
JavaScript arrow functions are often used in React applications for keeping the code concise and readable. I love them, teach them early, but always try to refactor my functions from JavaScript ES5 to ES6 functions along the way. At some point, when the differences between JavaScript ES5 functions and JavaScript ES6 functions become clear, I stick to the JavaScript ES6 way of doing it with arrow functions. However, I always see that too many different syntaxes can be overwhelming for React beginners. So I try to make the different characteristics of JavaScript functions clear before going all-in using them in React. In the following sections, you will see how JavaScript arrow functions are commonly used in React.
Functions as Components in React
React uses the best of different programming paradigms. That’s only possible because JavaScript is a many-sided programming language. On the object-oriented programming side, React’s class components are a great way of leveraging the abilities of JavaScript classes (inheritance for the React component API, class methods and class properties such as this.setState()
and this.state
). On the other side, there are lots of concepts from functional programming used in React (and its ecosystem) too. For instance, React’s function components are another way of defining components in React. The question which led to function components in React: What if components could be used like functions?
It’s a function which receives an input (e.g. props) and returns the displayed HTML elements (view). Under the hood, the function only needs to use the rendering mechanism of the render()
method from React components:
Function components are the preferred way of defining components in React. They have less boilerplate, add less complexity, and are simpler to maintain than React class components. You can easily migrate your class components to function components with React Hooks.
Previously, the article mentioned JavaScript arrow functions and how they improve your React code. Let’s apply these kind of functions to your function components. The previous Greeting component has two different looks with JavaScript ES5 and ES6:
JavaScript arrow functions are a great way of keeping your function components in React concise. Even more when there is no computation in between and thus the function body and return statement can be left out.
React Class Component Syntax
React’s way of defining components evolved over time. In its early stages, the React.createClass()
method was the default way of creating a React class component. Nowadays, it isn’t used anymore, because with the rise of JavaScript ES6, the previously used React class component syntax became the default (only before React function components were introduced).
However, JavaScript is evolving constantly and thus JavaScript enthusiast pick up new ways of doing things all the time. That’s why you will find often different syntaxes for React class components. One way of defining a React class component, with state and class methods, is the following:
However, when implementing lots of React class components, the binding of class methods in the constructor – and having a constructor in the first place – becomes a tedious implementation detail. Fortunately, there is a shorthand syntax for getting rid of both:
By using JavaScript arrow functions, you can auto-bind class methods without having to bind them in the constructor. Also the constructor can be left out, when not using the props, by defining the state directly as a class property. (
Note: Be aware that class properties are not in the JavaScript language yet.) Therefore you can say that this way of defining a React class component is way more concise than the other version.
Template Literals in React
Template literals are another JavaScript language specific feature that came with JavaScript ES6. It is worth to mention it shortly, because when people new to JavaScript and React see them, they can be confusing as well. When learning JavaScript, it’s the following syntax that you grow up with for concatenating a string:
Template literals can be used for the same which is called string interpolation:
You only have to use backticks and the ${}
notation for inserting JavaScript primitives. However, string literals are not only used for string interpolation, but also for multiline strings in JavaScript:
Basically that’s how larger text blocks can be formatted on multiple lines. For instance, it can be seen with the recent introduction of GraphQL in JavaScript, because GraphQL queries are composed with template literals. Also React Styled Components makes use of template literals.
Map, Reduce and Filter in React
What’s the best approach teaching the JSX syntax for React beginners? Usually I start out with defining a variable in the render()
method and using it as JavaScript in HTML in the return block.
You only have to use the curly braces to get your JavaScript in HTML. Going from rendering a string to a complex object isn’t any different.
Usually the next question then is: How to render a list of items? That’s one of the best parts about explaining React in my opinion. There is no React specific API such as a custom attribute on a HTML tag which enables you to render multiple items in React. You can use plain JavaScript for iterating over the list of items and returning HTML for each item.
Having used the JavaScript arrow function before, you can get rid of the arrow function body and the return statement which leaves your rendered output way more concise.
Pretty soon, every React developer becomes used to the built-in JavaScript map()
methods for arrays. It just makes so much sense to map over an array and return the rendered output for each item. The same can be applied for custom tailored cases where filter()
or reduce()
make more sense rather than rendering an output for each mapped item.
In general, that’s how React developers are getting used to these JavaScript built-in functions without having to use a React specific API for it. It is just JavaScript in HTML.
var, let, and const in React
Also the different variable declarations with var
, let
and const
can be confusing for beginners to React even though they are not React specific. Maybe it is because JavaScript ES6 was introduced when React became popular. In general, I try to introduce let
and const
very early in my workshops. It simply starts with exchanging var with const in a React component:
Then I give the rules of thumb when to use which variable declaration:
(1) don’t use
var
anymore, becauselet
andconst
are more specific(2) default to
const
, because it cannot be re-assigned or re-declared(3) use
let
when re-assigning the variable
While let
is usually used in a for loop for incrementing the iterator, const
is normally used for keeping JavaScript variables unchanged. Even though it is possible to change the inner properties of objects and arrays when using const
, the variable declaration shows the intent of keeping the variable unchanged though.
Ternary Operator in React
But it doesn’t end with displaying JavaScript strings, objects, and arrays in React. What about an if-else statement for enabling conditional rendering? You cannot use an if-else statement directly in JSX, but you can return early from the rendering function. Returning null is valid in React when displaying nothing.
However, if you want to use an if-else statement within the returned JSX, you can do it by using a JavaScripts ternary operator:
Another way of doing it, if you only return one side of the conditional rendering anyway, is using the &&
operator:
I will not go into detail why this works, but if you are curious, you can learn about it and other techniques for conditional rendering over here: All the conditional renderings in React. After all, the conditional rendering in React only shows again that most of React is only JavaScript in JSX and not anything React specific.
Import and Export Statements in React
Fortunately, the JavaScript community settled on one way to import and export functionalities from files with JavaScript ES6 with import and export statements.
However, being new to React and JavaScript ES6, these import and export statements are just another topic which requires explanation when getting started with your first React application. Pretty early you will have your first imports for CSS, SVG or other JavaScript files. The create-react-app project already starts with those import statements:
It’s great for the starter project, because it offers you a well-rounded experience how other files can be imported and (exported). Also the App component gets imported in the src/index.js file. However, when doing your first steps in React, I try to avoid those imports in the beginning. Instead, I try to focus on JSX and React components. Only later the import and export statements are introduced when separating the first React component or JavaScript function in another file.
So how do these import and export statements work? Let’s say in one file you want to export the following variables:
Then you can import them in another file with a relative path to the first file:
So it’s not necessarily about importing/exporting components or functions, it’s about sharing everything that is assignable to a variable (leaving out CSS or SVG imports/exports, but speaking only about JS). You can also import all exported variables from another file as one object:
Imports can have an alias. It can happen that you import functionalities from multiple files that have the same named export. That’s why you can use an alias:
All the previous cases are named imports and exports. But there exists the default statement too. It can be used for a few use cases:
to export and import a single functionality
to highlight the main functionality of the exported API of a module
to have a fallback import functionality
Leave out the curly braces for the import to import the default export:
Furthermore, the import name can differ from the exported default name. You can also use it in conjunction with the named export and import statements:
And import the default or the named exports in another file:
You can also spare additional lines and export the variables directly for named exports:
These are the main functionalities for ES6 modules. They help you to organize your code, to maintain your code, and to design reusable module APIs. You can also export and import functionalities to test them.
Libraries in React
React offers state management and side-effect features, but apart from this, it is only a component library which renders HTML for your browser. Everything else can be added from APIs (e.g. browser API, DOM API), JavaScript functionalities (e.g. map, filter, reduce) or external libraries. It’s not always simple to choose the right library for complementing your React application, but once you have a good overview of the different options, you can pick the one which fits best to your tech stack.
For instance, fetching data in React can be done with the native fetch API:
But it is up to you to use another library to fetch data in React. Axios is one popular choice for React applications:
So once you know about your problem which needs to be solved, React’s extensive and innovative ecosystem should give you plenty of options solving it. There again it’s not about React, but knowing about all the different JavaScript libraries which can be used to complement your application.
Async/Await in React
In a React Function Component, fetching data looks slightly different with React Hooks:
In the previous code snippet, we have used the most common way to resolve a promise with a then-block. The catch-block for error handling is missing for keeping the example simple. Please read one of the referenced tutorials to learn more about fetching data in React with error handling.
Anyway, you can also use async/await which got introduced to JavaScript not long ago:
In the end, it’s just another way of resolving promises in asynchronous JavaScript.
Higher-Order Functions in React
Higher-order functions are a great programming concept especially when moving towards functional programming. In React, it makes total sense to know about these kind of functions, because at some point you have to deal with higher-order components which can be explained best when knowing about higher-order functions in the first place.
Higher-order functions can be showcased in React early on without introducing higher-order components. For instance, let’s say a rendered list of users can be filtered based on the value of an input field.
It’s not always desired to extract functions, because it can add unnecessary complexity, but on the other side, it can have beneficial learning effects for JavaScript. In addition, by extracting a function you make it testable in isolation from the React component. So let’s showcase it with the function which is provided to the built-in filter function.
The previous implementation doesn’t work because the doFilter()
function needs to know about the query
property from the state. So you can pass it to the function by wrapping it with another function which leads to a higher-order function.
Basically a higher-order function is a function which returns a function. By using JavaScript ES6 arrow functions, you can make a higher-order function more concise. Furthermore, this shorthand version makes it more attractive composing functions into functions.
Now, the doFilter()
function can be exported from the file and tested in isolation as pure (higher-order) function. After learning about higher-order functions, all the fundamental knowledge is established to learn more about React’s higher-order components, if you want to learn about this advanced technique in React. Moving functions around your code base is a great way to learn about the benefits of having functions as first class citizens in JavaScript. It’s powerful when moving your code towards functional programming.
Shorthand Object Assignment
There is one little addition in the JavaScript language which leaves beginners confused. In JavaScript ES6, you can use a shorthand property syntax to initialize your objects more concisely, like following object initialization:
When the property name in your object is the same as your variable name, you can do the following:
Shorthand method names are also useful. In JavaScript ES6, you can initialize methods in an object more concisely:
Finally, you are allowed to use computed property names in JavaScript ES6:
You are able to use computed property names to allocate values by key in an object dynamically, a handy way to generate lookup tables (also called dictionaries) in JavaScript.
Destructuring in React
Another language feature introduced in JavaScript is called destructuring. It’s often the case that you have to access plenty of properties from your state or props in your component. Rather than assigning them to a variable one by one, you can use destructuring assignment in JavaScript.
That’s especially beneficial for React’s Function Components, because they always receive the props
object in their function signature. Often you will not use the props but only its content, so you can destructure the content in the function signature.
The destructuring works for JavaScript arrays too:
As you have already seen, React Hooks are using the array destructuring to access state and state updater function.
Another great feature is the rest destructuring. It is often used for splitting out a part of an object, but keeping the remaining properties in another object.
Afterward, the list can be used to be rendered, for instance in a React component, whereas the remaining state (here counter
) is used somewhere else. That’s where the JavaScript spread operator comes into play to forward the rest object to the next component. In the next section, you will see this operator in action.
Spread Operator in React
The spread operator comes with three …, but shouldn’t be mistaken for the rest operator. It depends on the context where it is used. Used within a destructuring (see above), it is as rest operator. Used somewhere else it is a spread operator.
The spread operator literally spreads all the key value pairs of an object. In React, it comes in handy when props are just being passed down to the next component.
Rather than passing all properties of an object property by property, you can use the spread operator to pass all key value pairs to the next component.
Also you don’t need to worry about the object’s structure beforehand, because the operator simply passes everything to the next component.
There is more JavaScript than React
In conclusion, there is lots of JavaScript which can be harnessed in React. Whereas React has only a slim API surface area, developers have to get used to all the functionalities JavaScript has to offer. The saying is not without any reason: “being a React developer makes you a better JavaScript developer”. Let’s recap some of the learned aspects of JavaScript in React by refactoring a higher-order component.
This higher-order component is only used for showing a conditional loading indicator when the isLoading
prop is set to true. Otherwise it renders the input component. You can already see the (rest) destructuring from the props and the spread operator in for the next Component. The latter can be seen for the rendered Component, because all the remaining properties from the props
object are passed to the Component as key value pairs.
The first step for making the higher-order component more concise is refactoring the returned React Class Component to a Function Component:
You can see that the rest destructuring can be used in the function’s signature too. Next, using JavaScript ES6 arrow functions makes the higher-order component more concise again:
And adding the ternary operator shortens the function body into one line of code. Thus the function body can be left out and the return statement can be omitted.
As you can see, the higher-order component uses various JavaScript and not React relevant techniques: arrow functions, higher-order functions, a ternary operator, destructuring and the spread operator. Basically that’s how JavaScript’s functionalities can be used in React applications in a nutshell.
Last updated