Use Interface Props in Functional Components Using TypeScript with React
Jun 29, 2020 • 9 Minute Read
Introduction
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.
Use Case
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.
Set Up a React TypeScript App
Open your terminal and run these commands to get a sample TypeScript app running on your machine.
npx create-react-app my-app --template typescript
cd my-app
yarn start
To run the app in development mode, open https://localhost:3000 in your browser. You should see the sample TypeScript app running.
Add a New Component
Create a new component inside your src directory with the name BudgetOverview.tsx and add this code.
import React from "react";
export const BudgetOverview = () => {
return <div className="Budget-Overview">
<table>
<tbody>
<tr className="Table-Header">
<td>
<h4>CATEGORY</h4>
</td>
<td>
<h4>BUDGETED</h4>
</td>
<td>
<h4>SPENT</h4>
</td>
<td>
<h4>REMAINING</h4>
</td>
</tr>
</tbody>
</table>
</div>
}
<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.
.App {
text-align: center;
}
.App-header {
background-color: #282c34;
min-height: 10vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
font-size: calc(10px + 2vmin);
color: white;
}
table {
display: flex;
justify-content: center;
border: 1px solid gray;
margin: 5vh;
}
td {
border: 1px solid gray;
width: 30em;
}
.Budget-Overview {
display: flex;
justify-content: center;
flex-direction: column;
}
.Table-Header {
background-color: #96bb7c;
}
Add a Budget Interface
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.
interface Budget {
budgeted: number,
spent: number,
category: string,
}
export default Budget;
Create a new file, src/interfaces.ts, and add the code for the Budget interface in that file.
Add Interface Props
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.
interface BudgetProps {
budgets: Budget[];
}
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.
import React from "react";
import Budget from "./interfaces";
interface BudgetProps {
budgets: Budget[];
}
export const BudgetOverview: React.FC<BudgetProps> = ({budgets}: BudgetProps) => {
return <div className="Budget-Overview">
<table>
<tbody>
<tr className="Table-Header">
<td>
<h4>CATEGORY</h4>
</td>
<td>
<h4>BUDGETED</h4>
</td>
<td>
<h4>SPENT</h4>
</td>
<td>
<h4>REMAINING</h4>
</td>
</tr>
{budgets.map(item => {
return <BudgetItem budgeted={item.budgeted}
spent={item.spent}
category={item.category}>
</BudgetItem>
})}
</tbody>
</table>
</div>
}
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.
const BudgetItem: React.FC<Budget> = ({category, budgeted, spent}: Budget) => {
const remainingAmount: number = (budgeted - spent) > 0 ? (budgeted - spent) : 0;
return <tr>
<td>
<h5>{category}</h5>
</td>
<td>
<h5>{"$" + budgeted}</h5>
</td>
<td>
<h5>{"$" + spent}</h5>
</td>
<td>
<h5>{"$" + remainingAmount}</h5>
</td>
</tr>
}
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.
Update the App Component
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.
import React from 'react';
import './App.css';
import {BudgetOverview} from "./BudgetOverview";
const homeBudgets = [
{
budgeted: 500,
spent: 200,
category: "Food",
},
{
budgeted: 1000,
spent: 1500,
category: "Utilities",
}
]
function App() {
return (
<div className="App">
<header className="App-header">Budget Table using TypeScript & React</header>
<BudgetOverview budgets={homeBudgets}/>
</div>
);
}
export 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 https://localhost:3000. You should see the budget overview in a tabular format.
Access the Code on GitHub
The code for this application is available on GitHub.
Conclusion
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.
Learn More
Explore these React courses from Pluralsight to continue learning: