Published on

1 - Fundamentals of React with TypeScript: Boost Your Web Development Career

Authors
  • avatar
    Name
    Jonas de Oliveira
    Twitter

In the realm of web development, React has established itself as a powerful library for building dynamic and scalable interfaces. By integrating TypeScript, developers gain an extra layer of safety and productivity, ensuring more robust applications with fewer bugs. In this article, we will explore the fundamentals of React with TypeScript, covering essential concepts such as TSX, components (both functional and class-based), props and state management with the useState hook, conditional rendering, and handling lists and keys.

TSX: Merging TypeScript with JSX

TSX is the file extension used when combining TypeScript with JSX, the syntax that allows you to write code resembling HTML within JavaScript. This combination brings several advantages:

  • Static Typing: TypeScript offers compile-time error detection, helping to prevent common issues.
  • Enhanced IDE Integration: Features like autocomplete, refactoring, and easy navigation are significantly improved when working with TSX.
  • Clarity and Organization: TSX structure allows for better component organization and clear identification of passed properties.

Basic example of a component in TSX:

import React from 'react';

// Define an interface for the properties that the Greeting component expects.
interface GreetingProps {
  name: string; // The "name" property is of type string.
}

// Functional component Greeting that receives properties defined in GreetingProps.
const Greeting: React.FC<GreetingProps> = ({ name }) => {
  // Returns an h1 element with a personalized message, using the "name" property.
  return <h1>Hello, {name}! Welcome to the world of React with TypeScript.</h1>;
};

// Exports the component so it can be used in other parts of the application.
export default Greeting;

Components: Functional vs. Class-Based

In React, components are the building blocks of the user interface. There are two main ways to define them: using functions and classes.

Functional Components

Functional components are the most recommended approach today, especially with the advent of hooks, which allow for simpler and more intuitive state and lifecycle management.

import React, { useState } from 'react';

// Define an interface for the properties of the Counter component.
interface CounterProps {
  initialValue?: number; // Optional property that defines the initial value of the counter.
}

// Functional component Counter that uses the useState hook to manage the counter state.
const Counter: React.FC<CounterProps> = ({ initialValue = 0 }) => {
  // Initialize the "count" state with the value of initialValue or 0 if not provided.
  const [count, setCount] = useState(initialValue);

  return (
    <div>
      {/* Displays the number of times the button has been clicked */}
      <p>You clicked {count} times.</p>
      {/* Button that, when clicked, increments the counter by 1 */}
      <button onClick={() => setCount(count + 1)}>Click Here</button>
    </div>
  );
};

export default Counter;

Class-Based Components

Although less common nowadays, class-based components are still in use, especially in legacy code. They offer lifecycle methods that can be useful in certain situations.

import React, { Component } from 'react';

// Define an interface for the state of the Clock component.
interface ClockState {
  time: Date; // The "time" property will store the current date/time.
}

// Class component Clock, which does not receive any properties (empty props) and uses the state defined by ClockState.
class Clock extends Component<{}, ClockState> {
  // Optional variable to store the interval ID, needed to clear the interval later.
  intervalId?: number;

  // Constructor to initialize the component's state.
  constructor(props: {}) {
    super(props);
    // Initialize the state with the current date/time.
    this.state = { time: new Date() };
  }

  // Method called immediately after the component is mounted to the DOM.
  componentDidMount() {
    // Sets up an interval that updates the "time" state every second.
    this.intervalId = window.setInterval(() => {
      this.setState({ time: new Date() });
    }, 1000);
  }

  // Method called before the component is unmounted, used to clear the interval and prevent memory leaks.
  componentWillUnmount() {
    if (this.intervalId) {
      clearInterval(this.intervalId);
    }
  }

  // Render method to display the component.
  render() {
    // Displays the current time formatted as a locale string.
    return <h2>Current Time: {this.state.time.toLocaleTimeString()}</h2>;
  }
}

export default Clock;

Final Thoughts

Integrating React with TypeScript is a strategic step for any developer looking to build scalable, high-quality web applications. The static typing and benefits of autocompletion and code validation make the development experience safer and more productive. By mastering the fundamentals presented here—TSX, both functional and class-based components, state management with hooks, conditional rendering, and the proper use of lists and keys—you not only enhance your technical skills but also build a solid foundation to stand out in the job market and catch the attention of recruiters.