Post

Typescript Pt. 10 - Typescript in React

Introduction

Bootstrap a React-vite app with Typescript by running the following command:

1
npx create-vite@latest GIVEN-PROJECT-NAME

Be sure to replace GIVEN-PROJECT-NAME with the name of your project. Choose react-ts as the template when prompted.


Declaring function components

  • A function component is a function that returns a React element.
  • A function component can be declared using the function keyword.
  • It can also be declared using the arrow function syntax.
  • The React.FC type can be used to declare a function component when using the arrow function syntax.
  • The JSX.Element type can be used to declare the return type of a function component.
1
2
3
4
5
6
7
8
// App.tsx
import React from "react";

const App: React.FC = () => {
  return <div>Hello World</div>;
};

export default App;
  • Or
1
2
3
4
5
6
7
8
// App.tsx
import React from "react";

function App(): JSX.Element {
  return <div>Hello World</div>;
}

export default App;

Props with TypeScript

  • Props are used to pass data from one component to another.
  • Props are passed to a component as attributes.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// App.tsx

import React from "react";
import Greeting from "./Greeting";

const App: React.FC = () => {
  return <Greeting name="John" />;
};

export default App;

// Greeting.tsx

import React from "react";

type GreetingProps = {
  name: string;
};

const Greeting: React.FC<GreetingProps> = ({ name }) => {
  return <div>Hello {name}</div>;
};

export default Greeting;
  • Or
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// App.tsx

import React from "react";
import Greeting from "./Greeting";

function App(): JSX.Element {
  return <Greeting name="John" />;
}

export default App;

// Greeting.tsx

import React from "react";

type GreetingProps = {
  name: string;
};

function Greeting({ name }: GreetingProps): JSX.Element {
  return <div>Hello {name}</div>;
}

export default Greeting;
  • The general idea is to first declare the type of the props object or more preferably an interface.
  • Then use the type or interface to declare the type of the props parameter in the function component.

  • Another example:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
// ShoppingList.tsx

import React from "react";

interface Item {
  id: number;
  name: string;
  quantity: number;
}

interface ShoppingListProps {
  items: Item[];
}

export default function ShoppingList({
  items,
}: ShoppingListProps): JSX.Element {
  return (
    <div>
      <h1>Shopping List for {name}</h1>
      <ul>
        {items.map((item) => (
          <li key={item.id}>
            {item.name} - {item.quantity}
          </li>
        ))}
      </ul>
    </div>
  );
}

// App.tsx

import React from "react";
import ShoppingList from "./ShoppingList";

const App: React.FC = () => {
  const items = [
    { id: 1, name: "Eggs", quantity: 2 },
    { id: 2, name: "Bread", quantity: 1 },
    { id: 3, name: "Milk", quantity: 1 },
  ];

  return <ShoppingList items={items} />;
};

UseState with TypeScript

  • The useState hook is used to manage state in a function component.
  • The useState hook takes in an initial value and returns an array containing the current state and a function to update the state.
  • The useState hook can be used with TypeScript by declaring the type of the state.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// Counter.tsx

import React, { useState } from "react";

export default function Counter(): JSX.Element {
  const [count, setCount] = useState<number>(0);

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>Click me</button>
    </div>;
  )
};

// App.tsx

import React from "react";
import Counter from "./Counter";

const App: React.FC = () => {
  return <Counter />;
};

  • In case the state is an object, the type of the state can be declared using an interface.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
// Counter.tsx

import React, { useState } from "react";

interface CounterState {
  count: number;
}

export default function Counter(): JSX.Element {
  const [state, setState] = useState<CounterState>({ count: 0 });

  return (
    <div>
      <p>You clicked {state.count} times</p>
      <button onClick={() => setState({ count: state.count + 1 })}>
        Click me
      </button>
    </div>
  );
}

// App.tsx

import React from "react";
import Counter from "./Counter";

const App: React.FC = () => {
  return <Counter />;
};
  • In case the state is an array of objects, which starts as an empty array, the type of the state can be declared using an interface.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
// Counter.tsx

import React, { useState } from "react";

interface Item {
  id: number;
  name: string;
  quantity: number;
}

export default function Counter(): JSX.Element {
  const [items, setItems] = useState<Item[]>([]);

  return (
    <div>
      <p>You clicked {items.length} times</p>
      <button
        onClick={() =>
          setItems([...items, { id: items.length, name: "Eggs", quantity: 1 }])
        }
      >
        Click me
      </button>
    </div>
  );
}

// App.tsx

import React from "react";
import Counter from "./Counter";

const App: React.FC = () => {
  return <Counter />;
};
This post is licensed under CC BY 4.0 by the author.