ReactJS Training: Understanding React and TypeScript

Mariano Vazquez
Jan 2 · 11 min read
Image for post
Image for post

Si quieres leer la versión en Español de este artículo, haz click aqui.

In this exercise, we will introduce the two core libraries that we will use to develop web applications: React and TypeScript. For this, we’ll go through small but concrete examples that will help us to understand the main concepts, one at a time.

But before starting to code, we need to understand what we are going to do. Think about the most common user interface (UI) layout you’ve seen, and ask yourself:

  1. If I have to make this, where should I start? Do I have to do all by myself? Is there something out there that I can use?
  2. How can I split the work into different tasks? What are the most important ones?
  3. Is it possible to reuse what I’m going to do with other or future projects?
Image for post
Image for post
A typical back-office web application, displaying Products and their details

In the next sections, we will work together to propose answers to these questions.

Introduction: web-based development

Before starting to code, let’s do a quick recap of the foundational concepts of web development.

If you are familiar with these concepts, skip this sections and jump directly to Section 1.

  • Web applications are, basically, applications that can be executed by a (web) browser (Chrome, Firefox, Edge, Safari, Internet Explorer, etc.).
  • Web browsers only understand HTML, JavaScript and CSS.
  • HTML provides the basic structure of sites, aka its markup.
  • CSS is used to control presentation, formatting, and layout, aka its styles.
  • JavaScript is used to change the behavior of different HTML elements and CSS styles dynamically. Usually depending on the user interaction (e.g., a click of a button, a tap of the finger or even speech).

For instance, when you navigate to the Google site because you want to search for something, you are using a web application!

Image for post
Image for post
When searching about React in Google we are using a web application

In this case:

  1. The structure of the page is defined using HTML (the text displayed as results, the right section, etc.).
  2. How the structure of the site looks is configured using CSS (the color of the fonts, the design of the result items and how they are displayed, etc.).
  3. The user interaction is controlled with JavaScript code. For instance, what happens when someone types a question and press ENTER is configured with code.

The amount of things that we can do in any web application and the complexity of them has grown over time. Fortunately, we can now (re)use JavaScript libraries to avoid reinventing the wheel and reduce the repetitive work. React and TypeScript are some of these libraries.

Section 1: What ReactJS is and what it is for

Note: If you want to know more about ReactJS, go to its official Getting Started.

React is a JavaScript library for building user interfaces. One of the greatest things about React is that it changes the way you usually think about creating an app. It proposes you to split the logic into pieces, named components, following the single responsibility principle or SRP: every piece (component) should do only one thing.

Using our previous UI layout as an example, we can split the page in (for instance) the following components:

  • A TableComponent, to display all of our entities.
  • SearchComponent, to filter the entities we show.
  • DetailsComponent, to display information related to a selected entity.
  • SidebarPanelComponent, to encapsulate the logic of what we render in the left panel (the links and PROD button).
  • …and so on
Image for post
Image for post
A typical back-office web application, now split into different components

The way we split our layout into components is entirely arbitrary and, although it might look hard to do for you today, it will become easier over time. Trial and error will, in time, help us to decide what is the best answer in terms of reusability and maintenance.

Note: We can continue splitting the components we defined into smaller components, each one responsible of doing a single task. For instance, can you propose how to break the TableComponent component into smaller pieces?

React in action

React is a library that will help us to build our UI by splitting it into components. Let’s understand together what this means by reviewing the examples in the React documentation:

Open the Hello React! example by clicking here.

import React from "react";
import ReactDOM from "react-dom";
const App = () => <h1>Hello React!</h1>;
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

Take a few minutes to analyze the code. Notice that the <App/> component is a React function that only returns JSX syntax.

What is JSX? JSX is the de-facto syntax extension to render HTML elements in the React ecosystem. It’s not HTML, but the syntax is pretty similar. It may remind you of a template language, but it also comes with the full power of JavaScript. If you want to learn more about JSX, see here.

Browsers do not understand JSX. To make our code work in browsers, we need to transpile our code into JavaScript code that browsers can understand. We don’t need to worry about this for now, but you do need to realize that the end result of this code is plain, old JavaScript:

var App = () => React.createElement("h1", null, "Hello React!")
var rootElement = document.getElementById("root");
ReactDOM.render(React.createElement(App, null), rootElement);

We will now modify the example by providing to the <App/> component the ability to customize the message rendered. For this:

Replace the hardcoded message with a message parameter sent to the component:

const App = ({ message }) => <h1>{message}</h1>;

Provide a customizedmessage when initializing App component:

ReactDOM.render(<App message="Hello React!!" />, rootElement);

React Functions can receive arbitrary, read-only input via props (short for properties). These props model what the function returns. For instance, in our previous example, the message we output in the browser depends on the message property.

Note: As a general rule, all React functions & components must act as “pure functions” with respect to their props. Meaning that what they return (or render) in the browser is determined by its input values, without mutating the parameters/arguments received (also known as a “side effect”).

Let’s move to another example. Open the React Timer example by clicking here.

class Timer extends React.Component {
...
}
const App = () => <Timer />;
const rootElement = document.getElementById("root");
ReactDOM.render(App, rootElement);

Notice that we now have two files: an index.jsx file that initializes our app and a Timer.jsx file that defines a React component. This time, our React component is a class that extends from React.Component, has a constructor() and four other methods:

export default class Timer extends React.Component {

constructor(props) { ... }

tick() { ... }

componentDidMount() { ... }

componentWillUnmount() { ... }
render() {
return <div>Seconds: {this.state.seconds}</div>;
}
}

React lets you define components as classes or functions. When you extend from React.Component, the only requirement is to define a render() method, responsible for returning the JSX elements that will be displayed in the browser.

Additionally, a React class component provides other built-in methods that are executed at particular (but specific) times. You can hook your own code to these lifecycle methods by just implementing them. Some of these methods are the constructor(), componentWillMount(), componentWillUnmount(), but there are others.

Note: The render() method is an equivalent of the React function that we used in the previous example.

Check the code inside the componentDidMount() and componentWillUnmount().

export default class Timer extends React.Component {
...
componentDidMount() {
this.interval = setInterval(() => this.tick(), 1000);
}
componentWillUnmount() {
clearInterval(this.interval);
}
...
}

This code is in charge of initializing, executing and cleaning up the timer. And by using these two built-in methods, React guarantees to execute your code when the component is rendered in the DOM (“mounted” ) and when it is removed from the DOM (“unmounted”).

Note: If you want to know more about state and lifecycle, see here.

Finally, let’s review the last method. The custom tick() method updates the component's state by calling this.setState():

export default class Timer extends React.Component {
...
tick() {
this.setState(prevState => (
{ seconds: prevState.seconds + 1 }
));
}
...
}

Every React Component could store its local state in this.state. State is similar to props, but it is private and fully controlled by the component. The state MUST NOT be modified directly. Instead, you should always the this.setState() method and return a new state.

Note: The reason why you should not mutate the state directly is that a state update could potentially trigger a new execution of the render() method, redrawing the component. If you use this.setState() React will make this call for you, along with other calculations.

We are now in the last example of this section. Open the Questionnaire example by clicking here.

class Questionnaire extends React.PureComponent {
...
}
const App = () => <Questionnaire />;
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

Take a few minutes to analyze all the pieces of code involved and the responsibility of each one of them. Then, play with the checkboxes and see the results.

Open the Question.jsx and Answer.jsx and notice that these files model a React function (or React functional component) that receive different props and returns a result, modeled via JSX.

export default ({ question, value }) => (
<p>
<span>{`${question}: ${value}`}</span>
</p>
);

Open the Questionnaire.jsx file. Take a look at the methods used by rendering the different pieces of the component: the questions and the answers. Notice how we orchestrate all the drawing logic using the render() method.

export default class Questionnaire extends React.PureComponent {
...

renderQuestions() {
...
}
renderAnswers() {
...
}
render() {
return (
<React.Fragment>
{this.renderQuestions()}
{this.renderAnswers()}
</React.Fragment>
);
}
}

Note: React Fragment is a built-in component used to (logically) group a list of children without adding extra nodes to the DOM. If you want to learn more about it, click here.

Focus on the renderQuestions() method and locate the onChange prop. Notice that we pass to the onChange prop a this.handleQuestionChanged() method that will update the UI if the question is answered, and will store the value in the (Questionnaire) component’s state:

export default class Questionnaire extends React.PureComponent {
...
renderQuestions() {
...

return questions.map(question => (
<Question
key={question.id}
id={question.id}
text={question.text}
checked={question.value}
onChange={this.handleQuestionChanged}
/>
));
}
...
}

Observe that the way we handle the user interaction (via “events”) in a similar fashion plain JS code does:

  • All JSX elements expose a set of events (see all supported events here).
  • We can hook up to each event by attaching a function to it. By default, it will receive a SyntheticEvent object as the first argument, but you can change this.

Wrapping up

By reviewing these examples, we learned the following:

  1. In React, we usually use JSX to describe what the UI should look like.
  2. To customize what we output, we can send props to our React functions or components.
  3. React provides the React.Component class to help to encapsulate our code in components.
  4. The output of a render() method of a React.Component tells the browser what we want to draw.
  5. Each React component could have its own state to store values locally.
  6. You can capture user interactions by hooking a function or class method to a JSX events.
Image for post
Image for post
In React, data flows in one direction (top-down, from parent to child), and events flow from bottoms-up

Note: You can find a complete set of examples, each one focused on a single React concept, in the React documentation.

Section 2: What TypeScript adds to the mix

TypeScript is an open-source library developed and maintained by Microsoft to implement large-scale applications in JavaScript environments. It compiles to plain JavaScript, which runs on any browser, in Node.js, or in any JavaScript engine that supports ECMAScript 3 (or newer).

In essence, it’s a strict syntactical superset of JavaScript that adds optional static typing to the language at development time.

Image for post
Image for post
TypeScript has great IDE support nowadays

The main benefits of using this library are:

  • It has static checking and code refactoring and a broad set of highly-productive development tools and practices.
  • It lets you write code using the latest features and syntax, without worrying about the browser support (because it will compile to plain JS).
  • It won’t force you to use TypeScript: you can write JavaScript if you want.
  • Microsoft and Google maintain it. And Angular uses it.

TypeScript in action

Let’s see how TypeScript works using an example:

Open the TypeScript playground. This playground uses the same tools the VSCode IDE uses to interpret code.

In the drop-down located at the left of the page, select the option Hello world. Take your time to thoroughly read its code and understand what TypeScript is and does. If you want, continue with the other examples of the JavaScript Essentials section.

Now open the Classes 101 example. Let’s review it together:

Image for post
Image for post
TypeScript Classes 101 example
  • In the left panel, there is TypeScript code that defines the Vendor class and a method to welcome clients to the shop, identified by its name.
  • In the right panel, you can visualize the JavaScript equivalent, that was generated by transpiling the TypeScript code to ES2017. This is the code that the browser understands and can run.
  • Similarly, there is TypeScript code on the left that defines the FoodTruck class, and a method to welcome new clients.

Mouse over the FoodTruck instantiation on line 47. Notice that the IDE displays information about its constructor.

Image for post
Image for post
IDEs like VSCode provide IntelliSense for TypeScript code

Add a second argument to instantiate a FoodTruck, like "asado". Now, open the Developer console (or Developer tools) of your browser by right-clicking the page (but outside of the Editor, like in the blue navbar at the top). Then, click the Run button.

Hey! Our change is not shown in the console, that's not fair. To make it work, either add console.log(nameOnlyTruck.greet()); on line 48 or replace the line 54 with the nameOnlyTruck instance. And then click Run again.

Note: Every modern web browser includes a powerful suite of developer tools that help developers to understand what the browser interprets and find possible bugs in the code (HTML, JavaScript or CSS). It also shows you metrics like how long the page took to load and every other request the browser made (and is doing). If you want to deep dive on this, click here.

Finally, replace the string "asado" with the number 1. Now there is an error in the code telling you that “numbers are not allowed as arguments of the constructor”. Notice that this is shown in TypeScript panel and not in JavaScript (the right panel).

Image for post
Image for post
With IntelliSense, you can detect errors before running your code

Fix the issue by replacing the number 1 with a string value (like "helado").

And that’s it!

Wrapping up

With this simple example, we’ve learned that:

  • TypeScript code can be transpiled to a JavaScript code that any browser can execute. You can find its handbook here.
  • TypeScript allows you to define types the same way you do this in strongly typed languages. You can find its spec here.
  • All modern IDEs (VSCode, WebStorm, Atom, etc.) support TypeScript and can provide hints and error messages (IntelliSense), as well as static analysis (via tslint).

🎉

Remember that you can find the full training in this GitHub repository.

JavaScript In Plain English

New JavaScript + Web Development articles every day.

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store