Typescript in React
Tags: codenewbie, react, javascript, typescript
Published: 2022-08-10 07:03:46

## Table Of Contents
[1. Introduction](#chapter-1)
[2. Functionalities and Examples](#chapter-2)
[3. Conclusion](#chapter-3)

Another week, another post. Carrying on from my previous post about Typescript for beginners, I thought I would write a post about using typescript in a React application for beginners.

<a name="chapter-1">Introduction</a>
As the popularity of React exploded in recent years, the demand to build React applications using Typescript has increase significantly as well.

**Adding Typescript to React**

I typically use create-react-app boilerplate to start my react application. To add Typescript when creating our react app, just type this additional wordings:
``` javascript
npx create-react-app my-app --template typescript
```
Once the boilerplate is completed, open the file and we will notice that some files are named `.ts` or `.tsx`. There is also a new file generated called `tsconfig.ts`. This file is where all the magic happens for Typescript. Typescript looks for the tsconfig.json file in the project root folder, and that file provides configuration options for the compiler.

<a name="chapter-2">Functionalities and Examples</a>

Before we jump into the use cases of Typescript in React, lets have a quick overview on the different "Types" in Typescript. 

- **void**: denotes the absence of any type.
- **tuple**: works like an array, but the number of elements here is fixed. The types of elements in a tuple are known and can be of different types.
- **enum**: is a group of constant values that are closely related and known.
- **any**: allows us to assign the value of any type to a variable. Used when a value type is unknown
- **never**: is a type that contains no value, so we can’t assign any value to a variable with a never type.
- **union**: this describes a value that can be one of several types number | string | boolean
- **object**: To define an object type we list its properties and their types: {x:number, y:number}

There is a deeper dive on this types in the previous post. Do check it out for more information on this.

**React functional components**
With the release of react 16.8, majority of users have shifted away from using class components to functional components. A React Functional Component is a function that receives props objects and returns JSX elements. In React components, we need to consider the type of props coming in. Integrating Typescript with functional component is pretty straight forward as follows:

```Javascript
import {FC} from "react"

const Movies: FC<{title: string}> = ({ title }) => {
  return (
    <>
      <h1>{message}</h1>
    </>
  );
};
```
This is one of the ways to define a functional component with Typescript. We have assigned a `FC` type to the functional component. Well, FC is an alias for Function Component. Also, noticed we have assigned types for the props being passed into the component by declaring it right after `FC`.

**Interface**
Another way of assigning types to your props is by using an interface. Typescript interfaces are essential to enforcing a particular object shape. An interface is like an object that contains information about the object’s properties and types. It explicitly tells the Typescript compiler about the property names and the value types an object can have. Also, since TypeScript is able to infer the type of your variables, you can remove typing the component FC as well. So in the end, it will look like this:
```Javascript
import {FC} from "react"
// we can do it like this
const Movies: FC<{title: string, boxOffice: number}> = ({ title, boxOffice }) => {
  return (
    <>
      <h1>{message}</h1>
    </>
  );
};

// or with an interface
interface MovieProps{
 title: string;
 boxOffice: number;
}

const Movies = ({ title, boxOffice }: MovieProps) => {
  return (
    <>
      <h1>{message}</h1>
    </>
  );
};

// To keep the title prop optional. Just pass it this way
interface MovieProps{
 title?: string;
 boxOffice: number;
}
```
There are a few advantages for using interfaces. Firstly, the code is a little cleaner. Secondly, we can export the interface and use it in other parts of our code as a type as well by doing this: `export interface MovieProps` which ensures consistency in our code. We can also define our interfaces in a single file and reference from that file. Any changes made can also be made in one location. 

**Some React Hooks**

<u>useState</u>
For `useState` hooks, the type expected can be inferred from the initial value passed into `useState`. For example:
```Javascript
const [title, setTitle] = useState("");
// is equal to
const [title, setTitle] = useState<string>("");
```
Since an empty string is passed as an initial value, typescript has inferred that the value stored will be a string type. However, if we are going set initial value as `null` or `undefined`, we need to pass a `union` of types like this:
```Javascript
const [title, setTitle] = useState<string | null>(null);
```
And if we are expecting an object in the `useState` hook, we can use `interface` to define the object type and assign it as a type in useState.

<u>useRef</u>
In most cases, useRef is used to reference input elements in HTML. Something like this:
```Javascript
function movieSearch() {
  const inputTitle = useRef(null);
  return (
    <>
      <input ref={inputTitle} type="text" />
    </>
  );
}
```
In such cases, we can use a generic type and note that we dont need to assign null as a type for generic types as it accepts `null` already.
```Javascript
const inputTitle = useRef<HTMLInputElement>(null)
```

<u>useEffect</u>
Typing the useEffect hook is not required because they don’t deal with returning values. The cleanup function for the useEffect hook is not considered a value that can be changed either so we can write these hooks as normal.

**HTML events**
The most commonly HTML events are button events, onChange events and form submits. These are the following example on how to type those events.

```Javascript
import { useState, ReactElement, ChangeEvent, FormEvent } from "react";

const App = (): ReactElement => {
  const [title, setTitle] = useState<string | null>(null);
  const handleSubmit = (e: FormEvent) => {
    e.preventDefault();
    // handle event here...
  };
  return (
    <form onSubmit={handleSubmit}>
      <div>
        <span>Email:</span>
        <input
          type="email"
          name="email"
          onChange={(e: ChangeEvent<HTMLInputElement>) =>
            setTitle(e.currentTarget.value)
          }
        />
      </div>
      <div>
        <input type="Submit" value="Submit" />
      </div>
    </form>
  );
};
```
As seen from above, the events for submitting the form is typed as `FormEvent` as import from the react node module. As for the change event, it is typed as `ChangeEvent<HTMLInputElement>` as onChange prop is in an input element which handles a change event. as for button events, it is shown as:
```Javascript
<button onClick={ (e: MouseEvent<HTMLButtonElement, MouseEvent>) => console.log("Clicked")}>button</button>
```
Do note that for most of the time, button and change event types can be inferred by Typescript hence there is no need to explicitly assigned the types to such events.

<a name="chapter-3">Conclusion</a>
Well, there we go, this are the more commonly used types when using React with Typescript. This list is by no means exhaustive and I do realize I have not covered some critical parts such as generics, type definition for some hooks (useContext or useMemo) or typing different type of React components. However I have not apply Typescript consistently on these topics or understand the core concepts behind them to write about it confidently yet. Once I do, I will update this blog post with more information. For now, I believe the information in this post is sufficient enough to get start with Typescript in a React application. As always, more information can be found in the official document: https://www.typescriptlang.org/docs/handbook/react.html
Till next time. Take care and stay safe.