Writing function or class components in a React/TypeScript app often requires you to define the type of props passed to them. It enforces type checking so that the code adheres to the defined contract. This guide will cover how to strongly type the props in a function component with the TypeScript interface.
Consider a situation where your goal is to display a budget overview table on a web page. For each budget, a row in the table should be rendered to display each budget category, including the amount budgeted, amount spent, and amount remaining in a category. There could be one or more budgets to display in the table. You will create a function component to achieve this.
Open your terminal and run these commands to get a sample TypeScript app running on your machine.
1npx create-react-app my-app --template typescript
2cd my-app
3yarn start
To run the app in development mode, open http://localhost:3000 in your browser. You should see the sample TypeScript app running.
Create a new component inside your src
directory with the name BudgetOverview.tsx
and add this code.
1import React from "react";
2
3export const BudgetOverview = () => {
4 return <div className="Budget-Overview">
5 <table>
6 <tbody>
7 <tr className="Table-Header">
8 <td>
9 <h4>CATEGORY</h4>
10 </td>
11 <td>
12 <h4>BUDGETED</h4>
13 </td>
14 <td>
15 <h4>SPENT</h4>
16 </td>
17 <td>
18 <h4>REMAINING</h4>
19 </td>
20 </tr>
21 </tbody>
22 </table>
23 </div>
24}
<BudgetOverview>
returns a table containing a single row with four columns that serve as headings. The table will be filled with data shortly.
The next step is to add styles for the <BudgetOverview>
component. Replace the existing css
in the src/App.css
file with the code below.
1.App {
2 text-align: center;
3}
4
5.App-header {
6 background-color: #282c34;
7 min-height: 10vh;
8 display: flex;
9 flex-direction: column;
10 align-items: center;
11 justify-content: center;
12 font-size: calc(10px + 2vmin);
13 color: white;
14}
15
16table {
17 display: flex;
18 justify-content: center;
19 border: 1px solid gray;
20 margin: 5vh;
21}
22
23td {
24 border: 1px solid gray;
25 width: 30em;
26}
27
28.Budget-Overview {
29 display: flex;
30 justify-content: center;
31 flex-direction: column;
32}
33
34.Table-Header {
35 background-color: #96bb7c;
36}
The goal is to display the data for every budget in a table row. For that, you will first define a Budget
interface with three properties:
budgeted: number
- Amount budgeted towards a category. This should be of number
type.
spent: number
- Amount already spent in a category. This should also be of number
type.
category: string
- Name of the budget category. It should be of string
type. 1interface Budget {
2 budgeted: number,
3 spent: number,
4 category: string,
5}
6
7export default Budget;
Create a new file, src/interfaces.ts
, and add the code for the Budget
interface in that file.
With budget characteristics described, the <BudgetOverview>
component should accept budget data as props
.
You can achieve that by creating another interface, BudgetProps
, inside the src/BudgetOverview.tsx
file.
1interface BudgetProps {
2 budgets: Budget[];
3}
This interface has one property, budgets
, which is an array. Each element in this array should be of type Budget
(defined in src/interfaces.ts
).
The <BudgetOverview>
component can now accept the props
whose type is BudgetProps
, iterate over every element inside the budgets
array, and render it on the web page.
Update your <BudgetOvervie>
component as shown below to include the strongly typed props
.
1import React from "react";
2import Budget from "./interfaces";
3
4interface BudgetProps {
5 budgets: Budget[];
6}
7
8export const BudgetOverview: React.FC<BudgetProps> = ({budgets}: BudgetProps) => {
9 return <div className="Budget-Overview">
10 <table>
11 <tbody>
12 <tr className="Table-Header">
13 <td>
14 <h4>CATEGORY</h4>
15 </td>
16 <td>
17 <h4>BUDGETED</h4>
18 </td>
19 <td>
20 <h4>SPENT</h4>
21 </td>
22 <td>
23 <h4>REMAINING</h4>
24 </td>
25 </tr>
26 {budgets.map(item => {
27 return <BudgetItem budgeted={item.budgeted}
28 spent={item.spent}
29 category={item.category}>
30 </BudgetItem>
31 })}
32 </tbody>
33 </table>
34 </div>
35}
The <BudgetOverview>
component is a React function component of type BudgetProps
, which is denoted by React.FC<BudgetProps>
.
The type for budgets
is enforced with the code ({budgets}: BudgetProps)
. If you try to pass it an array of any type other than BudgetProps
, the compiler will throw an error.
Inside the table body, there is code to iterate over the budgets
array and return a component <BudgetItem>
with each iteration.
<BudgetItem>
accepts three props—budgeted
, spent
and category
—to render their values.
Here is the code for the <BudgetItem>
component. Add this inside the src/BudgetOverview.tsx
file.
1const BudgetItem: React.FC<Budget> = ({category, budgeted, spent}: Budget) => {
2 const remainingAmount: number = (budgeted - spent) > 0 ? (budgeted - spent) : 0;
3 return <tr>
4 <td>
5 <h5>{category}</h5>
6 </td>
7 <td>
8 <h5>{"$" + budgeted}</h5>
9 </td>
10 <td>
11 <h5>{"$" + spent}</h5>
12 </td>
13 <td>
14 <h5>{"$" + remainingAmount}</h5>
15 </td>
16 </tr>
17}
This component is also a React function component of type Budget
. If you remember, we defined a Budget
type (src/interfaces.ts
) with exactly these three properties. Again, using interface for props created a strict contract for components that will use <BudgetItem>
.
It returns a table row containing four columns. Each column renders the value of a budget category, amount budgeted in the category, amount spent, and amount remaining in the category. It also contains a bit of logic for calculating the remaining amount using the values of budgeted
and spent
. If spent
is more than budgeted
, it displays $0
remaining.
The <BudgetOverview>
component is ready. All you need is to call this function component and pass props
to it.
Go to the src/App.tsx
file and replace the code in the <App>
component with the code given below.
1import React from 'react';
2import './App.css';
3import {BudgetOverview} from "./BudgetOverview";
4
5const homeBudgets = [
6 {
7 budgeted: 500,
8 spent: 200,
9 category: "Food",
10 },
11 {
12 budgeted: 1000,
13 spent: 1500,
14 category: "Utilities",
15 }
16]
17
18function App() {
19 return (
20 <div className="App">
21 <header className="App-header">Budget Table using TypeScript & React</header>
22 <BudgetOverview budgets={homeBudgets}/>
23 </div>
24 );
25}
26
27export default App;
homeBudgets
is an array containing budgets. Each element in this array is of type Budget
and has three properties that were defined by the interface.
This array is passed as props
to the <BudgetOverview>
component.
Additionally, the <header>
component contains the updated text.
Go to the browser and open http://localhost:3000. You should see the budget overview in a tabular format.
The code for this application is available on GitHub.
This guide described how to use the TypeScript interface to define strongly typed props in a function component. They help define the contract for the caller components so that the compiler fails when the structure of props does not meet the interface requirement. If you are interested in digging deeper into the topic of Interfaces, check out the links below.
Explore these React courses from Pluralsight to continue learning: