React.js: fetching the weather data in the useEffect hook

This blog continues my React/TypeScript miniseries and the previous blogs are:

1. Let’s start coding with TypeScript and React.js
2. React.js: A functional component and its state
3. Using the React.js state hook in the weather app

In this blog, I’ll add the useEffect() hook to fetch the weather info in the app that we started in the previous blog, where you learned how to store the city in the state of the App component. But our ultimate goal is finding the weather in the given city by fetching the data from an external server. Using the terminology from functional programming, we need to write a function with side effects. As opposed to pure functions, the functions with side effects use the external data and every invocation may produce different results even if the function arguments remain the same.

In React’s functional components, we’ll be using the useEffect() hook for implementing the functionality with side effects. By default, React automatically invokes the callback function passed to useEffect() after every DOM rendering. Let’s add the following function to the App component from the previous blog:

useEffect(() => console.log("useEffect() was invoked"));

If you run the app with the browser console open, you’ll see the message “useEffect() was invoked” each time when you enter a character in the input field and the UI is refreshed. Every React component goes through a set of lifecycle events, and if you need you code to be executed after the component was added to the DOM or each time it was was re-rendered, the useEffect() is the right place for such a code. But if you want the code in useEffect() to be executed only once after initial rendering, specify an empty array as the second argument:

useEffect(() => console.log("useEffect() was invoked"), []);

The code in this hook will be executed only once, which makes it a good place for performing the initial data fetch right after the component has been rendered.

Let’s assume you live in London and would like to see the weather in London as soon as this app is launched. Start by initializing the city state with “London”:

const [city, setCity] = useState('London');

Now you’d need to write a function that would fetch the data for the specified city. The URL will include the following static parts (replace 12345 with your APPID).

const baseUrl = 'http://api.openweathermap.org/data/2.5/weather?q=';
const suffix = "&units=imperial&appid=12345";

In between, you need to place the name of the city, so complete URL may look like this:

baseUrl + 'London' + suffix

For making Ajax requests, we’ll use the browser’s Fetch API (see https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API). The function fetch() returns a Promise, and we’ll use the async/await keywords in our method getWeather() that can look like this:

const getWeather = async (city: string) => {
  const response = await fetch(baseUrl + city + suffix); 
  const jsonWeather = await response.json(); 
  console.log(jsonWeather); 
}

NOTE: I prefer using the async/await keywords for asynchronous code, but using promises with chained .then() invocations would also work here.

When you use a standard browser’s fetch() method, getting the data is a two-step process: You get the response first, and then you need to call the json() function on the response object to get to the actual data.

TIP: JavaScript developers often use third-party libraries for handling HTTP requests. One of the most popular ones is a promise-based library called Axios (see https://www.npmjs.com/package/axios).

Now you can use this function for the initial data fetch in the useEffect():

useEffect( () => getWeather(city), []);

If you want the code in useEffect() to be executed selectively only if a specific state variable changed, you can attach the hook to such a state variable. For example, you can specify that the useEffect() has to run only if the city gets updated as follows:

useEffect(() => console.log("useEffect() was invoked"),
                 ['city']);

The current version of the App component is shown below.

import React, { useState, useEffect, ChangeEvent } from 'react';

const baseUrl = 'http://api.openweathermap.org/data/2.5/weather?q=';
const suffix = "&units=imperial&appid=12345";

const App: React.FC = () => {

 const [city, setCity] = useState('London');

 const getWeather = async (city: string) => { 
      const response = await fetch(baseUrl + city + suffix);
      const jsonWeather = await response.json();
      console.log(jsonWeather);
  }

  useEffect( { () => getWeather(city) }, []);  // this line has an issue

 const handleChange = (event: ChangeEvent<HTMLInputElement>) => {
    setCity( event.target.value ); 
}

  return (
    <div>
      <form>
        <input type="text" placeholder="Enter city"
               onInput = {handleChange} />
        <button type="submit">Get Weather</button>
        <h2>City: {city}</h2>
      </form>
    </div>
  );
}

export default App;


The second argument of the useEffect() is an empty array, so getWeather() will be invoked only once when the App component is initially rendered.

Note: If you run this app, the browser’s console will show the following warning: React Hook useEffect has a missing dependency: ‘city’. Either include it or remove the dependency array react-hooks/exhaustive-deps. The reason is that inside this hook we use the state variable city, which is a dependency and should be listed in the array. This is not an error and for simplicity I’ll keep this code as is, but you should keep this in mind while designing your hooks.

Tip: For the in-depth coverage of the useEffect() hook, read the article by Dan Abramov “A complete guide to useEffect“.

Run this app with the browser console open, and it’ll print the retrieved JSON with the London weather:

The initial data fetch is complete for the default city, and it looks like a good idea to store the retrieved weather data in the component’s state. Let’s define a new type Weather as shown in listing below for storing the content of the properties name and main marked in the above screenshot.

export interface Weather {
  city: string; 
  humidity: number; 
  pressure: number; 
  temp: number;     
  temp_max: number; 
  temp_min: number; 
}

In the App component, we’ll add a new state variable weather and the function to update it as follows:

const [weather, setWeather] = useState(null);

Note that the hook useState() allows you to use a generic parameter for better type safety. Now we need update the function getWeather() so it saves the retrieved weather and city name in the component’s state as shown below:

async function getWeather(location: string) {
  const response = await fetch(baseUrl + location + suffix);
  if (response.status === 200){
    const jsonWeather = await response.json();
    const cityTemp: Weather = jsonWeather.main; 
    cityTemp.city=jsonWeather.name;  
    setWeather(cityTemp);  
  } else {
      setWeather(null);  
  }
}

This code takes the object jsonWeather.main and the city name from jsonWeather.name, and saves them in the state variable weather.

So far, our function getWeather() was invoked for the initial retrieval of the London weather by the hook useEffect(). The next step is to add the code to invoke getWeather() when the user enters any other city and clicks on the button Get Weather. This button is a part of the form (its type is submit), so we’ll add the event handler to the tag. The function handleSubmit() and the first version of the JSX:

const handleSubmit = (event: FormEvent) => { 
   event.preventDefault();  
   getWeather(city);  
 }

return (
   <div>
     <form onSubmit = {handleSubmit}>  
       <input type="text" placeholder="Enter city"
              onInput = {handleChange} />
       <button type="submit">Get Weather</button>
       <h2>City: {city}</h2>
       {weather &&  <h2>Temperature: {weather.temp}F</h2>}  
     </form>
   </div>
 );

In React, event handlers get instances of SyntheticEvent, which is an enhanced version of browser’s native events (see https://reactjs.org/docs/events.html for details). SyntheticEvent has the same interface as the browser native events (e.g. preventDefault()) but events work identically across all browsers.

To pass the argument to getWeather(city), we didn’t have to find the reference to the field on the UI. The component’s state city was updated as the user typed the name of the city, so the variable city already has the value displayed in the field. The next screenshot was taken after the user entered Miami and clicked on the button Get Weather.

What if the user enters the city that doesn’t exist or not supported by openweathermap.org? The server returns 404 and we should add the appropriate error handling. So far we have the following line to prevent displaying the temperature if the weather state is falsy:

{ weather &&  <h2>Temperature: {weather.temp}F</h2> }

In the next version of this app, we’ll create a type guard to check if the weather for the provided city was received or not. For now, let’s take a breather and recap what we did in this and the previous blogs in the weather app:

1. Applied for the APPID at openweathermap.org
2. Generated a new app and replaced the JSX with a simple
3. Declared the state city using the hook useState()
4. Added the function handleChange() that updated city on each change in the input field
5. Added the hook useEffect() that would be invoked only once on the app startup
6. Ensured that useEffect() invokes the function getWeather() that uses the fetch() API to retrieve the weather in London
7. Declared the state weather to store the retrieved temperature and humidity
8. Added the event handler handleSubmit() to invoke getWeather() after the user entered the city name and clicked on the button Get Weather
9. Modified the function getWeather() to save the retrieved weather in the state weather
10. Displayed the retrieved temperature on the web page under the form

This is all good, but you shouldn’t to program all the app logic in one App component, and in the next blog, we’ll create a separate component to be responsible for displaying the weather data.

The source code of the completed app is here. If you want to learn TypeScript quickly, get our book TypeScript Quickly.

Advertisement

Using the React.js state hook in the weather app

This blog continues my React/TypeScript miniseries and the previous blogs are:

1. Let’s start coding with TypeScript and React.js
2. React.js: A functional component and its state

In this blog, I’ll start developing an app that will let the user enter the name of the city and get the current weather there. I’ll develop this app gradually, and its first version won’t be fetching data from the weather server just yet. First, I’ll add a little HTML form to the App component, where the user will be entering the name of the city.

Second, I’ll add the code to fetch the real weather data from the weather server and the App component will display the weather.

Finally, I’ll create another component WeatherInfo, which will be used as a child of the App component. The App component will retrieve the weather data and will pass it to WeatherInfo, which will display the weather.

We’ll be getting real weather data from the weather service at http://openweathermap.org, which provides an API for making weather requests for many cities around the world. This service returns the weather information as a JSON-formatted string. For example, to get the current temperature in London in Fahrenheit (units=imperial), the URL could look like this: http://api.openweathermap.org/data/2.5/find?q=London&units=imperial&appid=12345

Creators of this service require you to receive the application ID, which is a simple process. If you want to run our weather app, do the same and replace 12345 in the above URL with your APPID.

The sample code for this weather app was initially generated by the following command:

create-react-app weather --typescript

Then, I replaced the JSX code in the app.tsx with a simple HTML form where the user could enter the name of the city and press the button Get Weather. Also, the entered city represents the state of this component, and the App will be updating its state as the user is entering the city name.

Adding a state hook to the App component

In the previous blog, you’ve got familiar with the useState() hook, and the first version of our App component defines its state with this hook as follows:

const [city, setCity] = useState('');

Now the value in the variable city has to be updated using the function setCity(). Our hook useState() initializes the variable city with an empty string, so TypeScript will infer the type of city as a string. The following listing shows the App component with the declared state, and the form defined in the JSX section. This code also has an event handler handleChange(), which is invoked each time the user enters or updates any character in the input field.

import React, { useState, ChangeEvent } from 'react';

const App: React.FC = () => {

const [city, setCity] = useState(''); // 1

const handleChange = (event: ChangeEvent<HTMLInputElement>) => { // 2
setCity(event.target.value); // 3
}

 return (
  <div>
    <form>
      <input type="text" placeholder="Enter city"
             onChange = {handleChange} /> // 4
      <button type="submit">Get weather</button>
    <h2>City: {city}</h2> // 5
    </form>
  </div>
 );
}

export default App;

1. Declaring the state city
2. Declaring the function to handle the input field events
3. Updating the state by invoking setCity()
4. Assigning the handler to the onChange attribute
5. Displaying the current state value

The input field defines the event handler onChange = {handleChange}. Note that we didn’t invoke handleClick() here; we just provided the name of this function. React’s onChange behaves as onInput and is fired as soon as the content of the input field changes. As soon as the user enters (or changes) a character in the input field, the function handleChange() is invoked; it updates the state, which causes the UI update.

There is no documentation on which types of the React events to use with specific JSX elements, and to avoid using an event: any as the argument in event handler functions, open the file index.d.ts in the directory node_modules/@types/react and search for “Event Handler Types”. This should help you to figure out that the proper type for the onChange event is a generic ChangeEvent that takes the type of a specific element as a parameter, i.e. ChangeEvent.

To illustrate the state updates, I’ve added the <h2> element that displays the current value of the state: <h2>Entered city: {city}</h2>. Note that for re-rendering the current value of the city, I didn’t need to write a jQuery-like code finding the reference to this <h2> element and changing its value directly. The invocation of setCity (event.target.value) forces React to update the corresponding node in the DOM.

In general, if you need to update the functional component’s state, do it only using the appropriate setXXX() function that’s returned by the hook useState():

By invoking setXXX() you let React know that the UI update may be required. If you update the state directly (e.g. city=”London”), React won’t update the UI. React may batch the UI updates before reconciliating the Virtual DOM with the browser’s one. The following screenshot was taken after the user entered Londo in the input field.

To see that React updates only the <h2> node in the DOM, run this app (npm start) with the Chrome Dev Tools open in the tab Elements. Expand the DOM tree so the content of the the <h2> element is visible, and start typing in the input field. You’ll see that the browser changes only the content of the <h2> element, while all other elements remain unchanged.

Working with component’s state is an internal function of the component. But at some point, the component may need to start working with external data, and this is where the useEffect() hook comes in, which we’ll discuss in the next blog.

If you want to learn TypeScript quickly, get our book TypeScript Quickly.

React.js: A functional component and its state

In the previous blog, I generated a new React/TypeScript app using the create-react-app tool. In this blog, you’ll get familiar with two types of React components, and what a component’s state is for.

Two types of React components

A React component can be declared either as a function or as a class. A functional component is implemented as a function and is structured as shown below (types are omitted).

const MyComponent = (props) => {  // 1

  // other functions may go here
  
  return ( 
    <div>...</div>   // 2
  )
}

export default MyComponent;

1. props is used to pass data to the components
2. Return the component’s JSX

Developers who prefer working with classes can create a class-based component, which is implemented as a subclass of React.Component and is structured as follows:

class MyComponent extends Component {   // 1

  render() {   // 2
    return (   // 3
      <div>...</div>
    );
  }

  // other methods may go here
}

export default MyComponent;

1. The class must be inherited from React.Component
2. The render() method is invoked by React
3. Return JSX for rendering

If a functional component would simply return JSX, the class-based one has to include the method render() that returns JSX. I prefer using functional components, which have several benefits over the class-based ones:

* A function is easier to read than a class and requires less code to write; there is no need to inherit the component’s code from any class either
* A functional component generates less code during Babel transpiling
* No instances are created for wrapping the function
* No need for the this reference
* Functions are easier to test than classes; assertions simply map props to the returned JSX

You should use class-based components only if you have to use the React version older than 16.8. In old versions, only the class-based components would support the component’s state and lifecycle methods.

If you use the current version of create-react-app with the –typescript option, the generated file App.tsx file will already have the boilerplate code of a functional component (i.e. a function of type React.FC) shown below.

import React from 'react';    // 1
import logo from './logo.svg';
import './App.css';

const App: React.FC = () => {  // 2
  return (    // 3
    <div className="App">  // 4
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
        <p>
          Edit <code>src/App.tsx</code> and save to reload.
        </p>
        <a
          className="App-link"
          href="https://reactjs.org"
          target="_blank"
          rel="noopener noreferrer"
        >
          Learn React
        </a>
      </header>
    </div>
  );
}

export default App;   // 5

1. Import React library
2. This is a functional component
3. Return the component’s template as a JSX expression ( it’s not a string)
4. In JSX, use className instead of the CSS selector class to avoid conflicts with the JavaScript keyword class
5. Export the component declaration so it can be used in other modules

I used version 3.0 of create-react-app. The older versions of this tool would generate a class-based component App. The generated App function returns the markup (or template), which React uses for rendering this component’s UI. During the build process, Babel will convert it into a pure JavaScript object JSX.element with the div container that will update the Virtual DOM (I’ll introduce it in a separate blog) and the browser’s DOM. This App component didn’t have a separate place for storing its data (a.k.a. state), and we’ll add it in the next section.

Managing the component’s state

A component’s state is the datastore that contains the data that should be rendered by the component. The data in the component’s state is preserved even if React re-renders the component. Whenever the code updates the component’s state, React updates the component’s UI to reflect changes caused by the user’s actions (e.g. button clicks or typing in the input fields) or other events. If you have a Search component, its state can store the last search criteria and the last search result.

Do not confuse the component’s state with the application’s state. The former is the storage of an individual component’s state while the latter stores the app’s data that may represent the data from multiple components, functions, or classes.

And how would you define and update the component’s state? This depends on how the component was created in the first place. We’re going to move back to class-based components for a minute so that you can understand the difference in dealing with state in class-based and functional approaches. Then we’ll return to functional components, which I recommend using.

Adding state to a class-based component

If you have to work with a class-based component, you could define a type representing the state, create and initialize an object of this type, and then update it as needed by invoking this.setState(…).

Let’s consider a simple class-based component that has a state object with two properties: the user name and the image to be displayed. For serving images we’ll use the web site called Lorem Picsum, which returns random images of the specified size. For example, if you enter the URL https://picsum.photos/600/150, the browser will show a random image having the width 600px and height 150px. The next listing shows such a class-based component with a two-property state object.

interface State { <1>
  userName: string;
  imageUrl: string;
}

export default class App extends Component {

  state: State = { userName: 'John', <2>
           imageUrl: 'https://picsum.photos/600/150' }; 

  render() {
    return (
      <div>
        <h1>{this.state.userName}</h1> <3>
        <img src={this.state.imageUrl} alt=""/> <4>
      </div>
    );
  }
}

1 Defining the type for the component’s state
2 Initializing the State object
3 Rendering the userName here
4 Rendering the imageUrl here

By looking at the code of the render() method, you can guess that this component would render John and the image. Note that we embedded the values of the state properties into JSX by placing them inside the curly braces, e.g. {this.state.userName}.

Any class-based component is inherited from the class Component, which has a property state and the method setState(). If you need to change the value of any state property, you must do it using this method, for example:

this.setState({userName: "Mary"});

By invoking setState() you let React know that the UI update may be required. If you update the state directly (e.g. this.state.userName=’Mary’), React won’t call the method render() to update the UI. As you might have guessed, the state property is declared on the base class Component.

Earlier, I listed the benefits of functional components over the class-based ones, and we won’t use class-based components any longer. In functional components, we manage state by using hooks introduced in React 16.8.

Using hooks for managing state in functional components

In general, hooks allow to “attach” behavior to a functional component without the need to write classes, create wrappers or use inheritance. It’s as if you say to a functional component, “I want you to have additional functionality while remaining a flat function”.

Hooks have their names started with the word use. For example, useState() is the name of the hook for managing the component’s state, while useEffect() is used for adding a side-effect behavior (e.g. fetching data from a server). In this section, we’ll focus on the useState() hook using the same example as in the previous section: a component whose state is represented by the user name and the image URL, but this time it’ll be a functional component.

The useState() hook allows you to store the state in one or more primitive variables as well as in an object. The following line shows you how to define a state for the user name.

const [userName, setUserName] = useState('John'); 

The function useState() returns a pair: the current state value and a function that lets you update it. Do you remember the syntax of array destructuring introduced in ECMAScript 6? The above line means that the hook useState() takes the string ‘John’ as an initial value and returns an array, and I use destructuring to get the two elements of this array into two variables: userName and setUserName. The syntax of array destructuring allows you to give any names to these variables. If you need to update the value of userName from John to Mary and make React to update the UI (if needed), do it as follows:

setUserName('Mary');

In your IDE, do CMD-Click or Ctrl-Click on the useState(), and it’ll open the type definition of this function, which will declare that this function returns a stateful value and a function to update it. The function useState() is not a pure function because it stores states somewhere inside React. It’s a function with side effects.

The next listing shows a functional component that stores the state in two primitives: userName and imageUrl and displays their values using JSX.

import React, {useState} from 'react'; <1>

const App: React.FC = () => {

  const [userName, setUserName] = useState('John');  <2>
  const [imageUrl, setImageUrl] = useState('https://picsum.photos/600/150'); <3>
  
  return (
    <div>
      <h1>{userName}</h1> <4>
      <img src={imageUrl} alt=""/>  <5>
    </div>
  );
}

export default App;

1 Importing the useState hook
2 Defining the userName state
3 Defining the imageUrl state
4 Rendering the value of the state variable userName
5 Rendering the value of the state variable imageUrl

Now let’s re-write the component from the previous listing so instead of two primitives, it’ll declare its state as an object with two properties: userName and imageUrl. The next listing declares an interface State and uses the useState() hook to work with the object of type State.

import React, {useState} from 'react';

interface State {   // 1
  userName: string;
  imageUrl: string;
}

const App: React.FC = () => {

  const [state, setState] = useState<State>({  // 2
    userName: 'John',
    imageUrl: 'https://picsum.photos/600/150'
  });  

  return (
    <div>
      <h1>{state.userName}</h1>  // 3
      <img src={state.imageUrl} alt=""/>  // 4 
    </div>
  );
}

export default App;

1. Defining the type for the component state
2. Defining and initializing the state object
3. Rendering the value of the state property userName
4. Rendering the value of the state property imageUrl

Note that the useState() is a generic function and during its invocation, I provided the concrete type State.

The source code of this sample app is located in the directory hello-world. Run the command npm start and the browser will render the window that look similar to the screenshot below (the image may be different though).

The user name and image are too close to the left border of the window, which is easy to fix with CSS. The generated app shown earlier had a separate file App.css with CSS selectors applied in the component with the className attribute; you can’t use the class attribute to avoid a conflict with the reserved JavaScript keyword class. This time, we’ll add the margin by declaring a JavaScript object with styles and using it in JSX. In the next listing, I added the variable myStyles and used it in the component’s JSX.

const App: React.FC = () => {

  const [state, setState] = useState<State>({
    userName: 'John',
    imageUrl: 'https://picsum.photos/600/150'
  });  

  const myStyles = {margin: 40};   // 1

  return (
    <div style ={myStyles}>       // 2
      <h1>{state.userName}</h1> 
      <img src={state.imageUrl} alt=""/> 
    </div>
  );
}

1. Declaring the styles
2. Applying the styles

With this margin, the browser will render the div with additional 40px of space around it as shown in the next screenshot.

Our first React app works and looks nice! It has one functional component that stores hard-coded data in the state object and renders them using JSX. It’s a good start, and in the next blog, we’ll start writing a new app that will have more functionality.

If you want to learn TypeScript quickly, get our book TypeScript Quickly.

Let’s start coding with TypeScript and React.js

I like the programming language TypeScript, and recently, I’ve been blogging about this language. Earlier, I’ve been blogging about programming in Angular with TypeScript. The time has come, and I’ll start a short series on programming in React.js with TypeScript.

The React.js library (a.k.a. React) was created by a Facebook engineer Jordan Walke in 2013, and today it has 1300 contributors and 130K stars on GitHub! According to Stack Overflow Developer Survey of 2019, it’s the second most popular JavaScript library (jQuery remains the most broadly used library), and in this blog series, I’ll show how to start developing web apps in React using TypeScript. React is not a framework but a library responsible for rendering views in the browser (think of the letter V in the MVC design pattern).

The main player of React is a component, and the UI of a web app consists of components having parent-child relations. But if Angular takes control of the entire root element of the Web page, React allows you to control a smaller page element (e.g. a div) even if the rest of the page was implemented with any other framework or in pure JavaScript.

You can develop React apps either in JavaScript or in TypeScript and deploy them using tools like Babel and Webpack, and without further ado let’s start by writing the simplest version of the Hello World app using React and JavaScript; we’ll switch to TypeScript a bit later.

Developing the simplest web page with React

I’ll show you two versions of a very simple web page written with React and JavaScript. Each of these pages renders Hello World, but if the first version uses React with no additional tooling, the second version will engage Babel.

In the real-world apps, a React app is a project with configured dependencies, tools and the build process, but to keep things simple, our first web page will have just a single file index.html, which loads the React library from CDN.

<!DOCTYPE html>
   <head>
     <meta charset="utf-8">
     <script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"> <1>
     </script> 
     <script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"> <2>
     </script> 
   </head>
   <body>
     <div id="root"></div>  <3>

     <script >
         const element = React.createElement('h1', <4>
                                             null, <5> 
                                             'Hello World'); <6>
         ReactDOM.render(element, 
                         document.getElementById('root')); <7>
      </script>

   </body>
</html>

1. Loading the React package from CDN
2. Loading the ReactDOM package from CDN
3. Adding the div with the id “root”
4. Creating the h1 element using createElement() function
5. We don’t send any data (props) to the h1 element
6. The text of the h1 element
7. Rendering the h1 inside the div

The processes of declaring the page content (React.createElement()) and rendering it to the browser’s DOM (ReactDOM.render()) are decoupled, and the former is supported by the API offered by the React object, while the latter is done by ReactDOM. Accordingly, we loaded these two packages in the heasd section of the page.

In React, all component’s UI elements have to be wrapped in one container, and this web page has a div element with the ID root that serves as such container for the content rendered by React. In the script, we prepare the element to render using React.createElement(), and then invoke ReactDOM.render() that finds the element with the root ID and renders it there.

In Chrome, right-click on Hello World and select the menu Inspect. It’ll open the Dev Tools showing the div with the h1 element inside.

The method createElement() has three arguments: the element, its props (data to be passed to the element) and content. In this case, we didn’t need to provide any props (think attributes) and used null here; I’ll explain what props are for in another blog. The content of h1 is “Hello World”, but it can contain child elements (e.g. ul with nested li elements), which could be created with the nested createElement() calls.

Open the file index.html in your browser, and it’ll render the text Hello World as shown next.

Invoking createElement() on the page that has only one element is fine, but for the page that had dozens of elements, this would become tedious and annoying. React allows you to embed the UI markup into the JavaScript code, which looks like HTML, but is JSX. Let’s see how our Hello World page could look like if we used JSX (note const myElement ) instead of invoking createElement().

<!DOCTYPE html>
    <head>
        <meta charset="utf-8">
        <script crossorigin 
           src="https://unpkg.com/react@16/umd/react.development.js"></script>
        <script crossorigin 
           src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>

        <script src="https://unpkg.com/babel-standalone/babel.min.js"></script> <!-- 1 -->
    </head>
    <body>
        <div id="root"></div>
         <script type="text/babel"> // <2>
           const myElement = <h1>Hello World</h1>; // <3>
           
           ReactDOM.render( // <4>
                 myElement, 
                 document.getElementById('root')
           );

           console.log(myElement); // <5>
        </script> 

    </body>
</html>

1. Adding Babel from CDN
2. The type of the script is text/babel
3. Assigning a JSX value to a variable
4. Initiating the rendering of myElement to the div
5. Monitoring the JavaScript object that was rendered

This app renders the same page as seen in the screenshot above, but it’s written differently. The JavaScript code has embedded string <h1>Hello World!<h1> that looks like HTML to you, but it’s actually JSX. Browsers can’t parse this, so we need a tool to turn JSX into a valid JavaScript. Babel to the rescue!

The <head> section has an additional <script> tag that loads Babel from the CDN. Also, I changed the type of our script to text/babel, which tells Babel to transform the content of this <script> tag into JavaScript.

We wouldn’t use CDN for adding Babel to a Node-based project as we did in the code above, but for demo purposes, it suffices. In the Node-based apps, Babel would be installed locally in the project and it would be a part of the build process.

The next screenshot shows the browser’s console open. Babel converted the JSX value to a JavaScript object that was rendered inside the div, and we printed this object in the console.

Now that you have a fair understanding of how the very basic pages that use React, let’s switch to Node-based projects and component-based apps and see some tooling that React developers use in the real world.

Generating and running a new React-TypeScript app with create-react-app

If you want to create a React app that includes a transpiler and a bundler, you’d need to add configuration files to your app, and this process is automated by the command-line interface (CLI) called create-react-app (see https://www.npmjs.com/package/create-react-app). This tool generates all required configuration files for Babel and Webpack, so you can concentrate on writing your app instead of wasting time configuring tooling. To install the package create-react-app globally on your computer, run the following command in the Terminal window:

npm install create-react-app -g

Now you can generate either a JavaScript or a TypeScript version of the app. To generate the TypeScript app, run the command create-react-app followed by the app name and the –typescript option:

create-react-app hello-world --typescript

In a minute or so, all required files will be generated in the directory hello-world and the project dependencies will be installed. In particular, it installs the following React packages:

* react – a JavaScript library for creating user interfaces
* react-dom – React package for working with the DOM
* react-scripts – scripts and configurations used by create-react-app

Besides the above packages, the CLI installs Webpack, Babel, TypeScript, their type definition files, and other dependencies. To launch the generated web app, switch to the directory hello-world and run npm start, which in turn runs react-scripts start. Webpack will bundle the app and webpack-dev-server will serve the app on localhost:3000 as shown in the next screenshot.

For bundling, Webpack uses the file webpack.config.js located in the directory node_modules/react-scripts/config.

The good part is that if you generated the project with create-react-app, it’ll recompile the code, rebuild the bundles, and re-render the UI. This functionality is provided by the Webpack Dev Server. The UI of this app tells us to edit the file src/App.tsx (tsx is for TypeScript + JSX), which is the main TypeScript file of the generated app. Open the directory in VS Code, and you’ll see the project files as shown in the next screenshot.

The source code of your app is located ins the src directory, and the public directory is for the assets of your app that shouldn’t be included in the app bundles. For example, your app has thousands of images and needs to dynamically reference their paths, and the directory public is for files that don’t require any processing before deployment.

The file index.html contains an element <div id=”root”>, which serves as a container of the generated React app. You won’t find any <script> tags for loading the React library code there; they’ll be added during the build process when the app’s bundles are ready.

You can run the app and open the Chrome Dev Panel under the Elements tab to see the runtime content of index.html.

The file serviceWorker.ts is generated just in case you want to develop a Progressive Web App (PWA) that can be started offline using cached assets. We are not going to use it in our sample apps.

As you see, some of the files have an unusual extension .tsx. If we’d be writing the code in JavaScript, the CLI would generate the app file with the extension .jsx (not .tsx).

JSX and TSX

The draft of the JSX specification offers the following definition: “JSX is an XML-like syntax extension to ECMAScript without any defined semantics. It’s NOT intended to be implemented by engines or browsers”.

JSX stands for JavaScript XML. It defines a set of XML tags that can be embedded inside the JavaScript code. These tags can be parsed and turned into regular HTML tags for rendering by the browser, and React includes such a parser. The next screenshot shows the Babel’s REPL with a sample JSX.

On the left, we selected the preset react and pasted a sample code from the JSX spec. This preset means that we want to turn each JSX tag into React.createElement() invocation. The sample code should render a dropdown with a menu containing three menu items. On the right, you see how the JSX was parsed into JavaScript.

Every React app has at least one component, which is called a root component, and our generated app has only the root component App. The file with the code of the function App has the name extension .tsx, which tells the TypeScript compiler that it contains JSX. But just having the extension .tsx is not enough for tsc to handle it: you need to enable JSX by adding the jsx compiler option. Open the file tsconfig.json, and you’ll find there the following line:

"jsx": "preserve"

The jsx option only affects the emit stage – type checking is unaffected. The value preserve tells tsc to copy the JSX portion into the output file changing its extension to .jsx, because there will be another process (e.g. Babel) that will be parsing it. If the value would be react, tsc would turn the JSX tags into React.createElement() invocations as seen in the above screenshot on the right.

In the next blog, I’ll introduce two types of React components and what the component’s state is about. If you want to learn TypeScript quickly, get our book TypeScript Quickly.