React Functional Component Type

I’ve seen the ecosystem move from complex class components to the sleek world of functional components.

If you are using TypeScript with React, one of the first things you’ll need to master is how to properly type these functional components.

In this tutorial, I will walk you through everything you need to know about React functional component types, based on my years of experience in the trenches of web development.

Types for Functional Components

When I first started mixing TypeScript with React, I wondered if it was worth the extra effort.

The answer is a resounding yes. Using types ensures that your components receive the correct data and prevents those annoying “undefined is not a function” errors.

It makes your code self-documenting, which is a lifesaver when you’re working on a large team or returning to a project after several months.

Method 1: Use the React.FC (or React.FunctionComponent) Type

The most common way I type components is using the React.FC (which stands for Function Component) interface.

This is a generic type provided by the @types/react package. It allows you to define the shape of your props right at the component level.

Let’s look at a practical example. Imagine we are building a simple dashboard for a New York-based real estate firm to display property listings.

import React from 'react';

// Defining the shape of our props
interface PropertyCardProps {
  address: string;
  price: number;
  city: string;
  zipCode: number;
  isAvailable: boolean;
}

// Using React.FC to type the component
const PropertyCard: React.FC<PropertyCardProps> = ({ address, price, city, zipCode, isAvailable }) => {
  return (
    <div style={{ border: '1px solid #ccc', padding: '15px', margin: '10px', borderRadius: '8px' }}>
      <h2>{address}</h2>
      <p>Location: {city}, NY {zipCode}</p>
      <p>Price: ${price.toLocaleString()}</p>
      <p>Status: {isAvailable ? 'Available for Viewing' : 'Under Contract'}</p>
    </div>
  );
};

export default PropertyCard;

You can see the output in the screenshot below.

React Functional Component Type

In this example, React.FC<PropertyCardProps> tells TypeScript that this function is a React functional component and that its props must match the PropertyCardProps interface.

One thing I like about React.FC is that it provides type checking for properties like displayName and defaultProps automatically.

Method 2: Type Props Directly (The Standard Function Way)

While React.FC is popular, many senior developers I work with prefer typing the props directly in the function signature.

This approach is often cleaner because it treats the component like any other standard JavaScript function.

Let’s say we are building a shipping calculator for an e-commerce store based in Chicago.

import React from 'react';

interface ShippingTrackerProps {
  orderId: string;
  carrier: 'FedEx' | 'UPS' | 'USPS';
  estimatedDelivery: string;
}

// Typing the props directly in the arguments
export default function ShippingTracker({ orderId, carrier, estimatedDelivery }: ShippingTrackerProps) {
  return (
    <div className="tracker-container">
      <h3>Track Your Package</h3>
      <p><strong>Order ID:</strong> {orderId}</p>
      <p><strong>Carrier:</strong> {carrier}</p>
      <p><strong>Estimated Arrival:</strong> {estimatedDelivery}</p>
    </div>
  );
}

You can see the output in the screenshot below.

Functional Component Type in React

I find this method particularly useful because it handles “children” more explicitly.

Unlike older versions of React.FC, this method requires you to explicitly add children to your interface if you plan to use it, which I believe leads to better type safety.

Method 3: Type Components with Optional Props

In real-world US applications, you often have data that isn’t always available.

For instance, a user profile might not always have a middle name or a secondary phone number.

In TypeScript, we use the ? symbol to mark these as optional. Let’s look at a California-based tech talent profile component.

import React from 'react';

interface DevProfileProps {
  fullName: string;
  role: string;
  yearsOfExperience: number;
  linkedInUrl?: string; // Optional prop
  githubUsername?: string; // Optional prop
}

const DevProfile: React.FC<DevProfileProps> = ({ fullName, role, yearsOfExperience, linkedInUrl, githubUsername }) => {
  return (
    <div className="profile-card">
      <h1>{fullName}</h1>
      <p>Role: {role}</p>
      <p>Experience: {yearsOfExperience} years</p>
      
      {linkedInUrl && (
        <a href={linkedInUrl} target="_blank" rel="noreferrer">LinkedIn Profile</a>
      )}
      
      {githubUsername && (
        <p>GitHub: github.com/{githubUsername}</p>
      )}
    </div>
  );
};

export default DevProfile;

You can see the output in the screenshot below.

Functional Component Type React

When you use this component, TypeScript won’t complain if you omit linkedInUrl. This is a pattern I use daily to keep components flexible.

Handle Event Types in Functional Components

A big part of typing functional components is handling events like clicks or form submissions.

I’ve seen many developers use the any type here, but that defeats the purpose of TypeScript. Instead, use the built-in React event types.

Here is a search bar example for a Texas-based grocery delivery app.

import React, { useState } from 'react';

const GrocerySearch: React.FC = () => {
  const [query, setQuery] = useState<string>('');

  // Typing the change event
  const handleInputChange = (event: React.ChangeEvent<HTMLInputElement>) => {
    setQuery(event.target.value);
  };

  // Typing the form submission
  const handleSearch = (event: React.FormEvent) => {
    event.preventDefault();
    console.log(`Searching for ${query} in Austin, TX...`);
  };

  return (
    <form onSubmit={handleSearch}>
      <input 
        type="text" 
        value={query} 
        onChange={handleInputChange} 
        placeholder="Search for groceries..." 
      />
      <button type="submit">Find Stores</button>
    </form>
  );
};

export default GrocerySearch;

Using React.ChangeEvent<HTMLInputElement> gives you full intellisense for the event.target object, which makes coding much faster.

Best Practices I’ve Learned

After building dozens of production-ready apps, here are a few tips for typing your React components:

  1. Prefer Interfaces over Types: While both work, an interface is generally more extensible and offers better error messages in most IDEs.
  2. Export Your Interfaces: Often, you’ll need the same prop shape in a parent component or a test file. Exporting the interface makes your code more reusable.
  3. Avoid ‘any’: It might be tempting when you’re in a rush, but it almost always leads to bugs later.
  4. Use Union Types for Constants: If a prop only accepts specific strings (like ‘Small’, ‘Medium’, ‘Large’), use a union type instead of just a string.

Work with Hooks in Typed Components

Functional components rely heavily on hooks. You should type your useState and useRef hooks to ensure consistency within the component.

Here is an example of a simple tax calculator component for a freelance consultant in Seattle.

import React, { useState, useRef } from 'react';

interface TaxResult {
  total: number;
  taxAmount: number;
}

const SeattleTaxCalc: React.FC = () => {
  // Typing useState with an interface
  const [result, setResult] = useState<TaxResult | null>(null);
  
  // Typing useRef for an HTML input
  const amountRef = useRef<HTMLInputElement>(null);

  const calculateTax = () => {
    const amount = parseFloat(amountRef.current?.value || '0');
    const waTaxRate = 0.1025; // 10.25% for Seattle
    
    setResult({
      total: amount + (amount * waTaxRate),
      taxAmount: amount * waTaxRate
    });
  };

  return (
    <div className="calc-box">
      <label>Enter Amount (USD): </label>
      <input ref={amountRef} type="number" />
      <button onClick={calculateTax}>Calculate WA Tax</button>

      {result && (
        <div>
          <p>Tax Amount: ${result.taxAmount.toFixed(2)}</p>
          <p>Total: ${result.total.toFixed(2)}</p>
        </div>
      )}
    </div>
  );
};

export default SeattleTaxCalc;

In this case, useState<TaxResult | null>(null) tells TypeScript that the state starts as null but will eventually hold an object matching our TaxResult interface.

Using types for your React functional components might feel like extra work at first.

However, once you get the hang of it, you’ll find that it makes your development process much smoother and your apps much more stable.

You may also read:

51 Python Programs

51 PYTHON PROGRAMS PDF FREE

Download a FREE PDF (112 Pages) Containing 51 Useful Python Programs.

pyython developer roadmap

Aspiring to be a Python developer?

Download a FREE PDF on how to become a Python developer.

Let’s be friends

Be the first to know about sales and special discounts.