Hello React and Typescript
Hello React and Typescript
Table of Contents
Introduction 0
Hello World Sample Code 1
Setting Up Samples 1.1
Component Basics 1.2
Components in Separate Files 1.3
Component Props and State 1.4
Component Interactivity 1.5
Accept User Input 1.6
Component Composition 1.7
Define Props and State Types 1.8
Form Input Types 1.9
Development Environment 2
IDE 2.1
Package Management 2.2
TypeScript Environment 2.3
Testing 2.4
Automation 2.5
React 3
TypeScript 4
TypeScript and React 5
References 6
Glossary 7
Glossary
2
Hello React and TypeScript
When I started this book my main focus was on sharing my experience in establishing a
development environment and dealing with some of the quirks with coding React apps with
TypeScript. I thought that I wouldn't explore many of the concepts in React or TypeScript,
but as I learned more I decided to write about them. The book won't provide a deep
inspection of all things React or TypeScript, but I will go deeper than just a simple Hello
World.
This book will hone in on possible integrations of the two in terms of a development
environment, coding paradigms and style. The scope is small and this should not be taken
as a best practices guide. This is just my personal practice and there are many ways to do
this kind of development. I just hope that this can equip you to explore more practices for
your particular set of problems that can be solved with React and TypeScript.
Expectations
This is a very simple book, but it is probably most useful if you understand JavaScript.
Overview
We will start by jumping into some code samples with the proverbial Hello World. We will do
a few examples where we start with a very basic display the text "Hello World" and add new
features to demonstrate the basics of React with TypeScript.
Next, we break down the automation used in the sample. We review IDEs, package
management, build, transpiling... and more.
Programming Language
Introduction 3
Hello React and TypeScript
This book will use ECMAScript 2015 (ES6). React and TypeScript discussions and source
code will be expressed in ES6 and above.
Introduction 4
Hello React and TypeScript
Hello World
To start this party off right we will jump right into a review of some code samples. We will be
using the proverbial Hello World app. I think this is a little more approachable than some of
the many ToDo demos and other more real world applications being used to tout React. I am
not saying the demos are bad, but React is a significant paradigm shift for many developers
and I think a slow build up is good for old dogs like myself trying to learn new tricks.
Exploring Hello World is great to get you grounded before exploring more "real world" type
applications. We will even take the basic Hello World a little farther than simply displaying
text to get exposure to the core concepts in React.
Sample Source
You can download the code samples with the link provided for each sample. You can also
get a copy of the source from the GitHub repository by cloning
https://github.com/charleslbryant/hello-react-and-typescript.git
ReactRouter
Immutable.js
Flux
Redux
GraphQL
Relay
Application Configuration Management
Session Management
Caching
Security
Tenant Management
User Management
Role Management
Authentication
Cookie
Token
OAuth
Authorization
and much more
Setting Up Samples
Requirements
All of the code samples have a couple requirements
This first sample is the source for the basic development environment. This includes the
packages and automation that will be used in the samples.
Note - to get the latest version of packages and automation you should clone the repository
from root, https://github.com/charleslbryant/hello-react-and-typescript.git . We will make
updates as we move along with new samples so version 0.0.1 is only a starting point.
Source Code
https://github.com/charleslbryant/hello-react-and-typescript/releases/tag/0.0.1
Installing
To install a sample you need to run npm to get the required dependencies. You should open
a console at the root path of the sample directory and run
npm install
Then
tsd install
These commands will install the required npm packages and TypeScript Typings.
gulp
This will kick off the default gulp task to run all the magic to compile TypeScript, bundle our
dependencies and code into one bundle.js file, and move all of the files need to run the
application to a dist folder, open the index.html page in a browser, and reload the site when
Setting Up Samples 7
Hello React and TypeScript
Setting Up Samples 8
Hello React and TypeScript
Source Code
https://github.com/charleslbryant/hello-react-and-typescript/releases/tag/0.0.2
src/index.html
<!DOCTYPE html>
<html lang="en">
<head>
<title>Hello World</title>
<link rel="stylesheet" href="css/bundle.css"/>
</head>
<body>
<div id="app"></div>
<script src="scripts/bundle.js"></script>
</body>
</html>
If you don't understand this, I recommend that you find an introduction to HTML course
online.
The important part of this file is <div id="app"></div> . We will tell React to inject its HTML
output to this div.
src/main.tsx
Component Basics 9
Hello React and TypeScript
public render() {
return (
<div>Hello World</div>
);
}
}
If you know JavaScript, this may not look like your mama's JavaScript. At the time I wrote
this ES6 was only 6 months old and this sample is written with ES6. If you haven't been
following the exciting changes in JavaScript, a lot of the syntax may be new to you.
This is a JavaScript file with a .tsx extention. The .tsx extenstion let's the TypeScript
compiler know that this file needs to be compiled to JavaScript and contains React JSX. For
the most part, this is just standard ES6 JavaScript. One of the good things about TypeScript
is we can write our code with ES6/7 and compile it as ES5 or older JavaScript for older
browsers.
The very top of this file is a JavaScript comment. This is actually how we define references
for TypeScript typing files. This let's TypeScript know where to find the definitions for types
used in the code. I am using a global definition file that points to all of the actual definitions.
This reduces the number of references I need to list in my file to one.
Component Basics 10
Hello React and TypeScript
The import statements are new in JavaScript ES6. They define the modules that need to
be imported so they can be used in the code.
const is one of the new ES6 variable declaration that says that our variable is a constant or
a read-only reference to a value. The root variable is set to the HTML element we want to
output our React component to.
class is a new declaration for an un-hoisted, stict mode, function defined with prototype-
based inheritance. That's a lot of fancy words and if they mean nothing to you, its not
important. Just knowing that class creates a JavaScript class is all you need to know or
you can dig in at https://developer.mozilla.org/en-
US/docs/Web/JavaScript/Reference/Classes.
extends says that the Main class will be created as a child of the React.Component<any,
any> class.
React.Component<any, any> is a part of the TypeScript typing definition for React. This is
saying that React.Component will allow the type any to be used for the components state
and props objects (more on this later). any is a special TypeScript type that basically says
allow any type to be used. If we wanted to restrict the props and state object to a specific
type we would replace any with the type we are expecting. This looks like generics in C#.
constructor(props: any) {
super(props);
}
The contructor method is used to initialize the class. In our sample, we only call
super(props) which calls the contructor method on our parent class React.Component
passing any props that were passed into our constructor. We are using TypeScript to define
the props as any type.
Component Basics 11
Hello React and TypeScript
In additon to calling super we could also initialize the state of the component, bind events,
and other tasks to get our component ready for use.
public render() {
return (
<div>Hello World</div>
);
}
Maybe the most important method in a React component is the render method. This is
where the DOM for our component is defined. In our sample we are using JSX. We will talk
about JSX later, just understand that it is like HTML and outputs JavaScript.
JSX is not a requirement. You could use plain JavaScript. We can rewrite this section of
code as
public render() {
return (
React.createElement("div", null, "Hello World")
);
}
The render method returns the DOM for the component. After the return statement you
put your JSX. In our sample, this is just a simple div that says Hello World. It is good practice
to wrap your return expression in parenthesis.
Lastly, we call DOM.render and pass Main , the React component we just created, and
root , the variable containing the element we want to output the component to.
That's it, pretty simple and something we can easily build upon.
Component Basics 12
Hello React and TypeScript
Source Code
https://github.com/charleslbryant/hello-react-and-typescript/releases/tag/0.0.3
src/main.tsx
We only have two changes to explore the main.tsx file.
public render() {
return (
<HelloWorld />//Return our new HelloWorld component
);
}
}
We added a new import to import the HelloWorld component.Notice that we use a relative
path to the component with no extension.
return (
<HelloWorld />
);
Instead of returning the markup directly, we are returning the HelloWorld component and
delegating the rendering of the markup to this new component. By having the markup in a
separate component we can add <HelloWorld /> multiple times and only have to change it
in one place. We have a single point of truth for what the markup for Hello World should be
and we can reuse it.
To use external components they have to be in scope, which is why we imported it. Another
point to make is that a React component needs to have only one root element. If we were to
add more markup or components here, we would have to wrap it in a parent element.
Example:
return (
<div>
<HelloWorld />
<HelloWorld />
</div>
);
This would display "Hello World" twice. Notice how we started the component name with an
uppercase letter, React expects components to start with uppercase and DOM elements to
start with lowercase.
src/helloworld.tsx
public render() {
return (
<div>Hello World!</div>
);
}
}
If you paid attention to the previous sample you will notice that this is almost exactly like the
old main.tsx. We copied main.tsx to a new file called helloworld.tsx. We gave the component
class a new name and we deleted the import for DOM. We don't need to import DOM
because we don't need to call anything from React.DOM.
That was pretty easy so I don't think that we need to review this code.
Source Code
https://github.com/charleslbryant/hello-react-and-typescript/releases/tag/0.0.4
src/main.tsx
/// <reference path="../typings/tsd.d.ts" />
public render() {
return (
<div>
<HelloWorld defaultName='World' />
</div>
);
}
}
return (
<div>
<HelloWorld defaultName='World' />
</div>
);
We are just passing defaultName to the HelloWorld component. This is doing exactly what
you think it is, its setting the default value for who we are saying Hello to. Notice that this
name is explicit in defining this input. It is a default value, the HelloWorld component can
change this value and the assumption is that it may be changed.
All DOM properties and attributes (including event handlers) should be camelCased to be
consistent with standard JavaScript style. https://facebook.github.io/react/docs/dom-
differences.html
src/helloworld.tsx
/// <reference path="../typings/tsd.d.ts" />
public render() {
return (
<div>
Hello { this.state.name }!
</div>
);
}
}
We made two changes to helloworld.tsx, but they are significant to the interactivity of our
little application.
constructor(props: any){
super(props);
this.state = { name: this.props.defaultName };
}
In the constructor we are setting the initial state for this component. this.state is a plain
JavaScript object. It is a mutable representation of the model for the view. this.state is
expected to change over time as events occur in the component. In this sample we are
object. The difference being it is an immutable representation data used by the component.
this.props should not be changed and they are passed in by parent components. If you
change props, they will be overwritten when the parent rerenders. Mutating props puts your
component in an inconsisten state, so don't do it.
return (
<div>
Hello { this.state.name }!
</div>
);
The next change is to the return value of the render method. We are using
this.state.name to set the name dispayed in the UI.
In this sample we use this.props to initialize this.state . We know that we want to update
the name of who we say hello to, so we are using a state object to represent the name. If we
didn't want to update name, we could use props directly. For example
return (
<div>
Hello { this.props.name }!
</div>
);
Using props like this is saying that we don't expect this component to change the name. In
fact, to make it explicit, we changed the name from defaultName to name . Also, main.txt
would have to be changed from passing defaultName to name . Using props means we
expect the parent to be in control of changing the value of props. Using state means we
expect the component to be in control of its own state.
Component Interactivity
This sample gives an basic example of using adding interactivity to a component.
Source Code
https://github.com/charleslbryant/hello-react-and-typescript/releases/tag/0.0.5
src/helloworld.tsx
/// <reference path="../typings/tsd.d.ts" />
public render() {
return (
<div>
Hello { this.state.name }!
<button
name = "Update"
onClick = { e => this.handleOnClic(e) }
>Update</button>
</div>
);
}
}
Component Interactivity 19
Hello React and TypeScript
This is a new method to handle the click event. We expect callers of this method to send the
event as an argument so we defined the argument as type any so we can accept any
event. We could define a specific or generic event type and restrict the argument to that
type. We also define the method as returning void or nothing.
In the method we are calling this.setState and updating the value of name . When we call
this.setState it causes the component to re-render with the new state.
return (
<div>
Hello { this.state.name }!
<button
name = "Update"
onClick = { e => this.handleOnClick(e) }
>Update</button>
</div>
);
We are adding a new HTML element, button (remember that HTML elements start with
lowercase letter). The interesting bit is that we are binding the element's onClick event to
the handleOnClick method. To bind the event handler with the event we are using the new
ES6 arrow function expression to simplify function context binding. Notice that the event
handler is camelCased which is consistent with JavaScript style.
One example of this, related to our use of the arrow function above, is function context
binding. There was a time when React automatically bound functions to this . If you aren't
a JavaScript developer there is a chance that you don't know that this in JavaScript is
Component Interactivity 20
Hello React and TypeScript
decoupling of this from their parent function allows us to reuse functions outside of the
parent, powerful and dangerous at the same time.
To get this function reuse we can define the context for a function and have this represent
what we want it to. In our example the arrow function is assigning this from the class
HelloWorld to the handleOnClick method. If we wanted, we could use this same method in
say a GoodByeWorld class and the arrow function could set the context of the handleOnClick
method.
Without the arrow function we would use JavaScripts bind method to achieve the same
effect. The arrow function is just some syntactic sugar for
onClick = { handleOnClick().bind(this) }
Component Interactivity 21
Hello React and TypeScript
Source Code
https://github.com/charleslbryant/hello-react-and-typescript/releases/tag/0.0.6
src/helloworld.tsx
/// <reference path="../typings/tsd.d.ts" />
public render() {
return (
<div>
<div>
<input
onChange={ e => this.handleOnChange(e) }
/>
</div>
<div>
Hello { this.state.name }!
</div>
</div>
);
}
}
The significant changes here are we removed the button and handleOnClick method. We
also added a text box and a handleOnChange method to handle changes as a user adds
input to the text box.
This is a new method to handle the onChange event. In the method we are calling
this.setState and updating the value of name in this.state to the value of the target
public render() {
return (
<div>
<div>
<input
onChange={ e => this.handleOnChange(e) }
/>
</div>
<div>
Hello { this.state.name }!
</div>
</div>
);
}
Here we added an input element and set its default value to this.props.name . We also
bound the text box's onChange event to handleOnChange method.
1. When the user enters something in the text box it triggers the onChange event.
2. The onChange event is handled by the handleOnChange method.
3. The handleOnChange method updates the value of name in this.state and triggers a
re-render of the component with this.setState .
4. this.setState ends in a call to the render method that updates the name in our
"Hello" message.
State is only changes as the result of an event. The Hello message is no bound to an
external model state and can only be updated as a result of an event being triggered by user
input. This is different than two way binding or bi-directional data flow where changes in a
model can also update the state of a view.
Components are representations of the state of a view over time. As events are triggered
over time they update state and re-render the component with the new state. The flow can
be seen as a stream of events that flow in one direction that eventually update component
state causing a component to re-render. If you know about CQRS, event streaming, or
stream processing, there are similar concepts in each. UDF is a redundant theme in learning
React, hence a redundant theme in this book.
The sample is a simple naive example because we aren't dealing with external or persisted
data. The scope of the example makes it a little hard to understand UDF. In the example we
don't have to worry about updating an external store.
If you are having trouble understanding UDF, when you learn about Flux it will makes more
sense. The Flux architecture helps you visualize data flow in a circular one way round trip.
Even though it may be hard to see UDF within the context of a single component the same
event flow is used to accomplish UDF in React whether within a single component, a Flux
architecture, or using Relay (another Facebook library). When you get into Flux or other data
flow patterns or libraries, UDF will be expanded to add additional concepts into the data flow.
If we were to use a bi-directional binding to an external model, we would not know why state
is being updated. Any number of views could have the same binding to the same model.
With bi-directional binding a change to a view or model could cause updates to multiple
models or views and it becomes hard to understand the data flow, especially when you are
trying to solve a Sev1 incident.
If you'd like to know more about UDF, there is a lot about it online that can be found with a
simple search. Actually, the original MVC pattern is an example of UDF. It was distorted
when it moved to web clients. If you'd like to dig into the theory behind React and UDF, you
can research Functional Reactive Programming -
https://en.wikipedia.org/wiki/Reactive_programming.
Component Composition
This sample gives a basic example of refactoring the Hello World application by composing
the UI with modular components.
Source Code
https://github.com/charleslbryant/hello-react-and-typescript/releases/tag/0.0.7
src/helloworld.tsx
/// <reference path="../typings/tsd.d.ts" />
public render() {
return (
<div>
<HelloForm
name = { this.state.name }
handleChange = { this.handleChange }
/>
<HelloContent
name = { this.state.name }
/>
</div>
);
}
}
Component Composition 26
Hello React and TypeScript
The HelloWorld component is updated to compose the same UI as the previous example
using two modular components, HelloForm and HelloContent .
To compose with components the components you want to compose have to be in scope. To
do this we import the components. HelloForm and HelloContent are imported by using the
import statement with the from value being the relative path to the component with no
extension.
public render() {
return (
<div>
<HelloForm
name = { this.state.name }
handleChange = { this.handleChange }
/>
<HelloContent
name = { this.state.name }
/>
</div>
);
}
The actual composition occurs in the render method. We add the HelloForm and
HelloContent components. Notice that the name of the components start with uppercase to
differentiate them from HTML elements. Each of the components accept some properties
and we pass them with a syntax that is similar to defining HTML attributes.
By composing UIs in this manner we move from an imperative style of building UIs to a
declarative one. Instead of defining every element and attribute we want to use in the UI we
delegate the definition to a modular reusable component.
Since the modular components are reusable we can compose multiple UIs with them. We
can compose with components developed by other teams. We get to focus on the unique
aspects of our domain and delegate other lower level concerns to modular components.
Component Composition 27
Hello React and TypeScript
src/helloform.tsx
/// <reference path="../typings/tsd.d.ts" />
public render() {
return (
<div>
<input
value={ this.props.name }
onChange={ e => this.props.handleChange(e) }
/>
</div>
);
}
}
Here we have a new component responsible for the collecting user input for our tiny
application. By now this code should be familiar. We just moved the input element from the
HelloWorld component and encapsulated it in this new component.
For this simple example we are storing all of our components in one folder. As your
application grows you may want to use a folder structure that makes the number of
component files more manageable. When you are at the point of doing this you will have to
address the reference path for the TypeScript typings. It will become a maintenance issue
having to keep the path in sync as you move components and build new folder structures,
but we won't go into that just yet.
src/hellocontent.tsx
Component Composition 28
Hello React and TypeScript
public render() {
return (
<div>
Hello { this.props.name }!
</div>
);
}
}
This is a component responsible for displaying the hello message. Again, this component is
a result of encapsulating this section of the DOM out of the HelloWorld component.
Stateless Components
One interesting observation about these components is that they are stateless. They don't
hold any state and they rely on a parent component to pass props to it in order to do its
work. This includes event handlers and data as you can see in the sample code.
When possible using stateless components are preferred in React. They help to improve
performance because they lessen the amount of processing that React has to do with the
component.
Component Composition 29
Hello React and TypeScript
Source Code
https://github.com/charleslbryant/hello-react-and-typescript/releases/tag/0.0.8
src/interfaces.d.ts
interface IHelloFormProps {
name: string;
handleChange(event: any): void;
}
interface IHelloContentProps {
name: string;
}
First order of business is to define the new types. Since we aren't passing in state to any
components we won't define types for state objects, but its the same concept.
We are defining the types in a type definition file (file extention d.ts). This is the same type of
file that we get from DefinitelyTyped. This is a scaled down example, but you can also use
the same technique to build your own type definitions for external modules that don't have a
current definition.
interface IHelloFormProps {
the shape of a type. Shape in this sense is a collection of methods and properties along with
their associated types. When you create objects of the type defined by the interface it is
expected that the object will have the same shape. If it doesn't, TypeScript will give an error
at compile time. If your IDE supports it, you can also get design time errors, code
completion, etc.
These types are not used in the JavaScript that is generated, it is just used for type checking
by the TypeScript compiler.
name: string;
handleChange(event: any): void;
Here we are defining the expected shape of objects that extend IHelloFormProps . Objects
are expected to have a property named name of type string and a method named
handleChange that accepts an argument named event of type any and has a return type
void .
Hopefully, you can understand the IHelloContentProps interface from the explanation of
IHelloFormProps .
src/helloform.tsx
/// <reference path="../typings/tsd.d.ts" />
/// <reference path="./interfaces.d.ts" />
public render() {
return (
<div>
<input
value={ this.props.name }
onChange={ e => this.props.handleChange(e) }
/>
</div>
);
}
}
The HelloWorld component is updated to use the new types, IHelloFormProps and
IHelloContentContent .
Here we are adding a reference to the new type definition file we created to hold our type
interfaces.
In our class declaration we are saying that we want to extend React.Component using
objects of type IHelloFormProps .
constructor(props: IHelloFormProps) {
src/hellocontent.tsx
/// <reference path="../typings/tsd.d.ts" />
public render() {
return (
<div>
Hello { this.props.name }!
</div>
);
}
}
Development Environment
One of the first thing to do before starting a new project is setting up a development
environment. It is important to establish a good working environment with the tools and
dependencies for effective and efficient development. Although we want an environment for
React and TypeScript development, it isn't very different than a standard JavaScript setup.
Development Environment 34
Hello React and TypeScript
IDE
To code React applications with TypeScript you can use any text editor. To make things
easier it may be worth it to get an integrated development environment (IDE) that has
features and plug-ins specifically for JavaScript and TypeScript development.
Choosing an IDE is a religious experience so I won't start an ideological war by saying use
this or that IDE. I would recommend looking at some of the popular ones active today:
Aptana - aptana.com
Atom - atom.io
Brackets - brackets.io
Cloud9 - c9.io - cloud based editor
Eclipse - eclipse.org
Komodo - komodoide.com
NetBeans - netbeans.org
Nuclide - nuclide.io/
Sublime - sublimetext.com
Vim - vim.org
Visual Studio Code - code.visualstudio.com
WebStorm - jetbrains.com/webstorm
I am probably missing some that others would consider popular. This is just a tip of the IDE
iceberg to give some ideas on what's available. Initially, the IDE you choose is not important.
I can say that I enjoy Atom, Brackets, Cloud9, Sublime and Visual Studio Code. Also, I am
intrigued by Facebooks IDE Nuclide because it is based on Atom and made with React
development in mind.
I won't vote for one over the other because they all work. Try a few IDE's and pick one that
fits your development style without having to jump through hoops to do common tasks. If
your goal is to get up to speed on React and TypeScript development, don't spend too much
time trying to find and configure the perfect IDE.
IDE 35
Hello React and TypeScript
PackageManagement
There can be many dependencies that need to be managed to enable development with
external libraries, frameworks, tools, and APIs. Since we are talking about a JavaScript
project, we will use the popular Node Package Manager (NPM) to manage most of our
dependencies. NPM is like NuGet or Maven, but for node modules.
Initialize NPM
To get going with npm create a directory for your project (name isn't important). Then open a
command prompt at the new directory. Now initialie npm for the project, run
npm init
This starts a utility to help you setup your project for npm. I usually update the description,
version and author info. The utility takes that data you enter and creates a package.json file.
You can think of package.json like package.config for NuGet or pom.xml for Maven. This file
will have a listing of all of the dependencies for the project.
Initial Dependencies
We will be using a few dependencies that we will install with NPM. We are able to separate
dependencies that are only needed for development from dependencies that are needed at
runtime. This is useful when you want to distribute an application. User's of your app won't
have to download your development dependencies if they don't need them.
Runtime Dependencies
Here is a list of our initial runtime dependencies
Package Management 36
Hello React and TypeScript
Development Dependencies
Here is a list of our development dependencies
Package Management 37
Hello React and TypeScript
TypeScript Environment
You can install TypeScript typings with tsd. When you install your typings are saved in
tsd.json. You can create a tsd.json file by running
tsd init
To make it easier, in the source code there is a tsd.json that includes all of the typings
necessary for the demo application. To install these typing just run
tsd install
This will get the typings and place them in the typings folder. In the typings folder there is a
tsd.d.ts file that has all of the typing references bundled into one file.
TypeScript Configuration
There are a lot of configurations that you can set for the TypeScript compiler. To help
manage the settings you can create a tsconfig.json file to hold the configuration.
We take advantage of this file in the Gulp task to compile TypeScript. Actually, in our gulpfile
we use the tsconfig in tsc.createProject('tsconfig.json') to create a project that we can
use in our compile task.
TypeScript Environment 38
Hello React and TypeScript
Testing
Coming Soon!
Sneak Peak - The test framework will be Jest, Facebooks fork of Jasmine.
https://github.com/facebook/jest/tree/master/examples/typescript
Testing 39
Hello React and TypeScript
Automation
Next, we will setup our build automation. The primary reason we want to do this is so we
don't have to run the commnand line every time we make changes. In fact, our build
automation will allow us to automatically see the results of changes in the browser after we
save them. We can start one simple task in the command line and the automation will take
care of linting, compiling, bundling, refreshing the browser and more when ever we make
changes.This allows us to get very fast feedback on changes. If we have fast unit tests, this
automation will also help us keep some bugs from creeping into our app. So, build
automation will not only make development go faster, provide faster feedback, help keep
quality high, it will also give us a consistent way to build our application.
Gulp
We are going to use Gulp for our task runner and Browserify to bundle. To be honest, I was
going to switch to npm and WebPack. The React community seems to have embraced
WebPack as the defacto bundler. So, there are plenty of examples online. Also, I went with
Browserify because the learning curve is bigger for WebPack and I don't want it to be a
distraction.
Actually, we are going to use Gulp 4. At the time of this writing, this new version of Gulp
hasn't been released. The main reason I decided to go with this early release version is that
it has new features that will make our automation a little easier to work with.
The main feature we want to exploit is the new task execution system. Before Gulp 4, all
tasks ran in parallel. This was great becuse it made things fast, but many times there is a
series of tasks that need to run in sequence. Getting tasks to run sequentially can get
complicated. With the new task execution we can define a pipeline of tasks and decide if we
want parallel or series execution.
First we need to install Gulp 4. Because I already have Gulp installed I need to firt uninstall
Gulp and then reinstall version 4.
npm uninstall --save-dev gulp
Automation 40
Hello React and TypeScript
If you have worked with Gulp before, you'll notice that I installed gulp and gulp-cli separate.
The CLI was moved to a separate module to make the core install lighter for use cases that
don't need the CLI.
Vinyl
Just some background on vinyl because it is interesting to me. Gulp uses vinyl, a virtual file
format, which is why we don't need to create temp files to pass through automation
workflows like Grunt. Files are converted to vinyl ( gulp.src() ) and can be piped to different
gulp middleware as they flow through gulp tasks and finally converted back to a physical file
( gulp.dest() ). Under the hood gulp uses the vinyl-fs module to work with files on a local file
system, but the "interesting to me" part of vinyl is that modules can be created to use vinyl to
work with any file source, DropBox, S3, Azure Storage... I haven't had a need to connect to
external files, but it was exciting to realize that I can come up with new use cases to
transform my build automation process with vinyl modules.
Automation 41
Hello React and TypeScript
React
React is a library for building composable user interfaces. It encourages the creation of
reusable UI components which present data that changes over time.
Tom Occhino and Jordan WalkeReact announced React as an open source project at
JSConfUS 2013 - https://www.youtube.com/watch?v=GW0rj4sNH2w. Pete Hunt followed up
in a talk he gave at JSConfEU and JSConfAsia. There were a lot of nay sayers as a result of
the announcement and Pete titled his talk after a sarcastic Twitter post, "React: Rethink Best
Practices." This talk goes into the design decisions behind React and gives solid reasons for
using it - https://www.youtube.com/watch?v=DgVS-
zXgMTk&feature=iv&src_vid=x7cQ3mrcKaY&annotation_id=annotation_3048311263.
For you functional minded folks, another way to think of React is as a way of writing
declarative views where a view is a function of data defined in terms of the state of data in
some point in time.
v = view
p = props
s = state
v = f(p,s)
React is a small library with a simple API. It is not an MVC framework. You can think of
React as the view in MVC. It just renders views and enables interactivity by responding to
events.
Facebook and Instagram developed React and actually use it in production on their very
large scale applications and development teams. You can write isomorphic applications by
rendering views on both the client and server with the same JavaScript code. With the
announcement of React Native you can render views on any device (IOS, Android...). Netflix
is using React to render UIs on televisions! Its hard to deny React as a viable option for
application development.
I think React has delivered on redefining best practices for efficiently developing and
rendering views.
React Component
React 42
Hello React and TypeScript
A React Component is just a JavaScript function. The function accepts an immutable object
named props and has a render function that can render a section of DOM which can include
child components. Having child component functions inside component functions allows you
to build up a DOM tree. The React Component encapsulates behavior to manage its state
and handle its life cycle events.
Basically, a React Component is a JavaScript function that owns a section of the DOM.
Components can be composed together with other components to build up a UI. If you build
components properly they become like Legos for UIs. Small, focused on a specific concern,
easy to reuse and repurpose them to build UIs to solve various problems.
JSX
React doesn't have a template system, but you can use markup that feels like HTML by
using JSX. JSX is an extension of JavaScript that allows you to use XML like constructs in
your components to define your view structure.
JSX is not a template it is a high level abstraction of the DOM. JSX must be transformed
before it is used. When you use a JSX transformer, with tools like Babel or TypeScipt
compiler, JSX elements are transformed to plain JavaScript React.createElement methods.
JSX gives us an abstraction that allows us to be more declarative while writing our view. We
are using familiar HTML like structure to declare what the DOM structure is. As opposed to
defining the DOM with a lot of React.CreateElement calls. Building a UI with
React.CreateElement is still declarative, but the declaration with JSX is a little easier to grok
There are some difference from HTML that you have to watch out for while writing JSX. You
can't use JavaScript keywords. For instance, instead of defining a CSS class attribute on
your JSX element you use className . Instead of using for to relate a label with an
element you use htmlFor .
When you want to render HTML elements you use lowercase as first letter of JSX element.
React 43
Hello React and TypeScript
<div className="container">
<label htmlFor="hello">Hello</label>
<input type="text" id="hello" />
</div>
When you want to render a React Component use uppercase as first letter of the JSX
element.
You could write your views with React.createElement instead of JSX, but JSX is more
approachable by designers and developers that aren't comfortable with JavaScript.
Writing React components with JSX we move from writing views with imperative, hard to
understand, underpowered HTML template logic to writing declarative, highly expressive
functions to manage the state of components with JavaScript. It's a win-win. Developers can
write logic with a proper development language and not a weird restrictive template
abstraction and Designers still get the comfort of working with HTML like structures.
React uses somthing it calls a two passes rendering process. First it generates the markup
in the first pass. Then it attaches events after the markup is injected in the document. This
allows React to generate documents on the server and send it to a client and React will
recognize that the markup is already done so it just attaches the events and the app
continues functioning from there. This makes it fast for the initial view of the app. Then the
speed of React keeps the app functioning fast.
You call setState any time the state for the component is updated. setState will mark the
component as dirty to help React optimize what actually needs to be re-rendered. When a
component is marked for rendering the children in its sub-tree will also be rendered. At the
React 44
Hello React and TypeScript
end of each event loop React will call render on all of the components that have been
marked dirty by setState . This means that during a single cycle React can render multiple
components in one batch.
If React determines that it should render it will render a virtual DOM. React compares the
virtual DOM from the previous render with the current render to decide what has been
updated in the DOM. When comparing the old and new DOM React compares nodes in the
DOM tree. If it finds a node that doesn't have the same element or component type, it will
remove the old one including its entire sub-tree and replace it with the new one. This
provides a big gain in terms of performance because React doesn't have to waste time
tyring to reconcile sub-trees if the parent nodes don't match.
To help React efficiently compare nodes you should assign child elements a key attribute
with a value that is unique among its siblings elements. This makes it easier for React to
compare elements. React compares the attributes of elements to determine if there was a
change. If a change was found, only the attributes that have changed are updated.
It is much more efficient for React to work with the virtual DOM made of JavaScript objects
than say a browser DOM. You can read more about the heuristics React uses to reconcile
the DOM to make the minimum number of changes to a device's DOM
https://facebook.github.io/react/docs/reconciliation.html.
React 45
Hello React and TypeScript
You can think of props as the components configuration or the external public API of the
component. Props are the external parameters that are passed into a component. Once
props are set don't expect them to stay in sync as the component goes through its lifecycle.
Within the component, props should be considered immutable or read only. After the
component is constructed props should not be changed. Parent components can pass props
to their child components. A component can set default values for props to keep default
values consistent when a props aren't passed in. Default props values will be overridden if
props are passed into the component.
In MVC you have mutable data or state in the form of models. Multiple views can depend on
a model. Changing a model could change multiple views. A view could change multiple
models. In large applications this many-to-many relationship can make it difficult to
understand what views depend on models and what models are updated from views.
Understanding how data flows and the state of the application over time can be a challenge.
The nature of the model view relationship also leads to funky circular dependencies that can
be ripe with hard to find bugs (like the well known issues with Global state).
React 46
Hello React and TypeScript
In React data or state is mutable, but it is private, not shared, and managed in components.
Because state is internal there are no side effects from shared state like MVC. When you
keep the number of stateful components low, it is easier to understand the state of your
application over time, hence easier to debug and maintain. We can use stateful components
to pass immutable properties to stateless components that will always be consistent with the
stateful component. When we know where, when, and how state changes and that
properties don't change once they are set there is a lot of guess work removed when we are
trying to debug or update our applications. By using the concept of stateful and stateless
components you can get a better handle on the state of your application at any point in time.
Stateful Components
A stateful component is a container that provides data or state service to stateless
components. They manage the state for itself and its child components. If we compare it to
DDD, a stateful component would be like an aggregate for a bounded context.
A stateful component maps its state to props that are passed down to stateless components
for consumption. The props are immutable and don't change once set and will always be
consistent with the stateful component that set them. Whenever state is updated (calling
this.setState ) the stateful component will render itself and all of its children, so children
A stateful component should handle events triggered by its children. Ideally, stateful
component wouldn't have props and would be able to compose its state on all its own,
independent of any parent or ancestors. It should be detached from its parent in terms of
rendering. It should only re-render when it has new state, not when it's parent re-renders. It
could possible use the shouldComponentUpdate to prevent re-rendering by parent.
shouldComponenUpdate(nextProps) {
return false;
//or return reference equality of immutable props
//return this.props === nextProps;
}
For clarity I would recommend naming stateful components with a "Container" suffix so that
it is evident that it is a stateful component (e.g. MyFunkyContainer , MyFunkyTestContainer ).
Stateless Components
React 47
Hello React and TypeScript
Stateless components don't hold state and depend on their stateful parent component
container for state. The stateless component can trigger events that would cause the stateful
component to update state and therefore update the stateless component. Stateless
components are reusable and they aren't dependent on a specific stateful component
container, but requires a parent container to pass props.
An element is a plain object describing what you want to appear on the screen in terms of
the DOM nodes or other components. Elements can contain other elements in their props.
Creating a React element is cheap. Once an element is created, it is never mutated.
Element Example
Here we are creating an element named DeleteAccount with a simple JavaScript arrow
function. This can be composed in a parent component where the parent would pass the
props that are needed by the element (e.g. string message and color and child elements in
the example). This cuts down on code of a full component class when you don't need to use
state, lifecycle events, and other React component class features.
Data Flow
Another way to look at the stateful-to-stateless component relationship is in terms of data
flow. Data is passed down the React component hierarchy in props (parent-to-child
communication). Props should be immutable because they are passed down every time
React 48
Hello React and TypeScript
higher components are re-rendered, so any changes in props would be loss on each re-
render. So, changing props after they are set is a good way to introduce bugs if you want
them, but why would you?
You can enforce props to be read-only in TypeScript by using a TypeScript property with only
a getter or in JavaScript ES5+ with object.defineProperty with writable set to false .
Defining props with persisted immutable data structure, like those found in immutable.js help
further in enforcing immutability and helps simplify comparisons when you need to compare
changes in props.
Event Flow
Events flow up the hierarchy and can be used to instruct higher components to update state
(child-to-parent communication). When you have components that need to communicate
that don't share a parent child relationship, you can write a global event system or even
better use a pattern such as Flux to enable cross component communication.
These flow rules allows us to easily visualize how data streams through our application.
React 49
Hello React and TypeScript
TypeScript
To use TypeScript typings in your code you have to provide a reference to the definition files.
This can be done with a reference
/// <reference path="someExternalModule.d.ts" />
If you modules are proper node modules, you should have to use a reference. If you have
problems importing a module that has a type definition, try including a reference to the type
definition.
I use tsd to import my type definitions. This creates a tsd.d.ts file that contains a reference to
all of the typings I have installed. I usually use this file as a reference instead of individually
listing each typing I want to reference.
/// <reference path="../typings/tsd.d.ts" />
This is a little of a maintenance issue because I am using relative paths and if I move the file
in the path heirarchy I have to update the reference path. There are ways to get around this
with a tsconfig file, but it is out of scope for this simple guide.
I have a lot of trouble with references and the internal module import system with TypeScript.
Using the reference and the root tsd.d.ts file has allowed me to use ES6 style import with
little friction, but it took me some searching to get over some nuances that aren't apparent.
Importing Modules
To get the strong typing in TypeScript it has to know about the types you will be using. You
can define your custom types as you build up your application, but if you are using third
party modules like React, you have to give TypeScript some help.
TypeScript 50
Hello React and TypeScript
To import an external module, like a node module, you just use the name of the module
instead of the path. TypeScript is smart enough to search in common locations for the
module.
TypeScript 51
Hello React and TypeScript
Below we have an example where we are exporting a component. Since there can be more
than one component in a namespace we mark our default component with the default
keyword. Even if there are no other components, setting default makes it easier to import the
component without having to define the default in the import statement.
Since the example doesn't use props or state and we haven't created types for them we
pass in any to let the IDE and TypeScript compiler know that any type is acceptable for
props and state. If we wanted to use props and state, we would create an interface to define
the type we are expecting.
This is just a simple guide, so any deeper is out of scope. If you would like to get more info
on React Components in TypeScript, I suggest taking a look at the type definition at
https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/react/react.d.ts. Unless the
signature has changed, you can do a search for type ReactInstance = Component<any, any> |
Element; to get a feel for how the type is constructed and what properties and methods are
available.
IMyComponentState are interfaces that define the types these objects should contain. If your
IDE support TypeScript it may be able to use these interfaces to give you visual feedback
when you have the wrong types. The TypeScript compiler will also use the interfaces to do
type checking. You can get a similar effect in normal React by using propTypes, but I enjoy
how TypeScript maps to my C# OOP braint, it makes the component cleaner and easier to
read in my opinion.
interface IMyComponentProps {
someDefaultValue: string
}
interface IMyComponentState {
someValue: string
}
public render() {
return (
<div>
Value set as {this.state.someValue}
</div>
);
}
}
This example is assuming that someValue may get changed over time because it is in a
state object (we aren't showing the code that would change the state to keep the code
simple). If we know that someValue won't change during the components lifetime we would
just use the props values directly in render ( Value set as {this.props.someDefaultValue} ).
Since props are immutable and shouldn't change, we only move props to state in the
constructor when we know the values will change.
References
1. React Documentation by Facebook - https://facebook.github.io/react/docs/getting-
started.html
2. React’s diff algorithm by Christopher Chedeau - http://calendar.perfplanet.com/2013/diff/
3. React.js Conf 2015 by Facebook - https://www.youtube.com/playlist?list=PLb0IAmt7-
GS1cbw4qonlQztYV1TAW0sCr
4. TypeScript Handbook by Microsoft - http://www.typescriptlang.org/Handbook
5. TypeScript Deep Dive by Basarat Ali Syed - https://basarat.gitbooks.io/typescript/
References 54
Hello React and TypeScript
Glossary
CQRS
Command Query Responsibility Segregation
DAG
[Directed acyclic graph - https://en.wikipedia.org/wiki/Directed_acyclic_graph]
(https://en.wikipedia.org/wiki/Directed_acyclic_graph)
3. React
DDD
Domain Driven Design
3. React
DOM
Document object model.
MVC
Model View Controller.
Glossary 55
Hello React and TypeScript
UDF
Unidirectional Data Flow
UI
User interface.
Glossary 56