Typing Props and State in Functional Components in React JS

Introduction

In React, functional components are a popular choice for writing components because of their simplicity and ease of use. TypeScript enhances functional components by providing a way to type both props and state, which helps catch errors during development and improves the developer experience.

This tutorial will walk you through how to type props and state in functional components using TypeScript in React.

Step 1: Setting Up TypeScript in a React App

Before typing props and state in functional components, you need to set up TypeScript in your React app. If you already have TypeScript set up in your React project, you can skip this step. If not, you can create a new React project with TypeScript using the following command:


  npx create-react-app my-app --template typescript
      

Alternatively, you can add TypeScript to an existing React app by installing the necessary TypeScript dependencies:


  npm install --save typescript @types/react @types/react-dom
      

After the installation, you'll need to rename your JavaScript files to .tsx (for JSX code) and configure TypeScript in your project by creating a tsconfig.json file if it's not already created.

Step 2: Typing Props in Functional Components

In TypeScript, you can define the types for props by using an interface or a type alias. The types will specify the expected structure of the props passed to the component.

Example: Typing Props with an Interface

Let's start by typing the props of a simple Greeting component that accepts a name prop of type string.


  import React from 'react';
  
  // Define the props type using an interface
  interface GreetingProps {
    name: string;
  }
  
  // Functional component with typed props
  const Greeting: React.FC = ({ name }) => {
    return 

Hello, {name}!

; }; export default Greeting;

In this example:

  • We created an interface GreetingProps to define the expected shape of the props.
  • The name prop is typed as a string.
  • We used React.FC to type the component itself as a functional component that receives GreetingProps as its props.

Example: Typing Props with Type Alias

Alternatively, you can use a type alias to type the props:


  import React from 'react';
  
  // Define the props type using a type alias
  type GreetingProps = {
    name: string;
  }
  
  const Greeting: React.FC = ({ name }) => {
    return 

Hello, {name}!

; }; export default Greeting;

Both methods (interface and type alias) are functionally equivalent, so you can use whichever you prefer based on your project requirements.

Step 3: Typing State in Functional Components

In React functional components, you can use the useState hook to manage state. With TypeScript, you can type the state to make sure it holds the correct type of data.

Example: Typing State with useState

Let's create a counter component where we type the state to ensure it is a number:


  import React, { useState } from 'react';
  
  const Counter: React.FC = () => {
    // Type the state with number
    const [count, setCount] = useState(0);
  
    const increment = () => setCount(count + 1);
  
    return (
      

Count: {count}

); }; export default Counter;

In this example:

  • We used the useState(0) hook to specify that the count state is of type number.
  • The state will only accept numbers, and if we tried to set a non-number value, TypeScript would throw an error.

Example: Typing State with Complex Types

If you need to manage a more complex state, like an object or array, you can use TypeScript's type annotations to define the expected structure of the state.


  import React, { useState } from 'react';
  
  // Define the type for the state
  interface User {
    name: string;
    age: number;
  }
  
  const UserInfo: React.FC = () => {
    // Type the state as an object with name and age properties
    const [user, setUser] = useState({ name: 'John', age: 30 });
  
    const updateAge = () => setUser({ ...user, age: user.age + 1 });
  
    return (
      

Name: {user.name}

Age: {user.age}

); }; export default UserInfo;

In this example:

  • The User interface defines the shape of the user state object.
  • We type the state with useState({ name: 'John', age: 30 }).
  • The state will now expect an object with a name (string) and an age (number).

Step 4: Using Optional Props and Default Values

Sometimes, props can be optional, or you may want to provide default values for them. You can use TypeScript's optional chaining and default parameters for this purpose.

Example: Optional Props

If a prop is optional, you can add a question mark (?) to the prop's type definition:


  import React from 'react';
  
  interface GreetingProps {
    name: string;
    age?: number; // Optional prop
  }
  
  const Greeting: React.FC = ({ name, age }) => {
    return (
      

Hello, {name}!

{age &&

Age: {age}

}
); }; export default Greeting;

In this example, the age prop is optional. If it's provided, the component displays it; otherwise, it is ignored.

Example: Providing Default Values

You can provide a default value for props using default function parameters:


  import React from 'react';
  
  interface GreetingProps {
    name: string;
    age?: number;
  }
  
  const Greeting: React.FC = ({ name, age = 25 }) => {
    return (
      

Hello, {name}!

Age: {age}

); }; export default Greeting;

Here, if the age prop is not passed, it will default to 25.

Conclusion

In this tutorial, we've learned how to type props and state in functional components using TypeScript in React. By typing props and state, you can catch errors early, improve code readability, and enhance the overall developer experience. TypeScript provides a powerful way to ensure type safety in your React components.





Advertisement