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.
Developing the simplest web page with React
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.
<!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
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.
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
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-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.
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”.
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:
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.
8 thoughts on “Let’s start coding with TypeScript and React.js”
I believe vue.js got fusion of angular & react plus learning curve is short compare to both. Only downside compare to react will be corporate level of acceptance for vue. Are you moving away from angular? Good to know your thoughts.
> Are you moving away from angular?
It’s like asking, “Are you moving away from Phillips screwdriver?” All web frameworks are tools to create an app for the user. I don’t remember hearing from any user “I don’t like this app because it’s developed with the framework XYZ”.
IMO, Angular is the best for developing enterprise apps. It has everything needed for developing any web app. The learning curve is a little higher than with Vue and is comparable with the equivalent React.js-based set of tools. But if your team develops in Angular, the requirements for the qualification of the programmers is lower: just know Angular. React is good for smaller teams with higher average qualification where developers like to experiment with different packages. Vue is trying to take the middle ground between Angular and React. So far, it’s easiest to learn but this may change with the release of Vue 3 next year.
If you ask my opinion, use any of the three, but don’t mix them in the same app.
Thanks for your reply. All three got good resources and mixing them in one project will be close to self-destruction (so point noted).
So asking your opinion on Dart won’t be out of your wheel zone. You were an advocate of language after Adobe let go very productive Flex technology. Google is back with a new framework Flutter for mobile & web development (hummingbird framework) using Dart. Just like flex you can do single-page app & mobile development from one single codebase ( flex code can run on mobile using Adobe Air runtime..old times). Do you see similarities to Flex? Again, your helpful opinion matters.
Hi Yakov, I have been following you online since early Adobe Flex (good ‘ol) days.
I have been working on Angular for quite some time now. Any specific reason to choose React with Typescript and not JS (Ecma)?
I wrote about why use TyoeScript here https://yakovfain.com/2018/09/10/why-program-in-typescript
It remains the same for any JS framework.