Introducció

TypeScript és un superconjunt de JavaScript que afegeix tipat estàtic al llenguatge. Utilitzar TypeScript amb React pot millorar la qualitat del codi, proporcionar una millor experiència de desenvolupament i ajudar a evitar errors comuns. En aquest tema, aprendrem com integrar TypeScript en un projecte de React i com utilitzar-lo per tipar components, props, estat i altres elements de l'aplicació.

Configuració de TypeScript en un projecte de React

Crear un nou projecte amb Create React App

Create React App (CRA) facilita la creació d'un nou projecte de React amb TypeScript. Per crear un nou projecte, executa la següent comanda:

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

Això crearà un nou projecte de React amb TypeScript ja configurat.

Afegir TypeScript a un projecte existent

Si ja tens un projecte de React i vols afegir-hi TypeScript, segueix aquests passos:

  1. Instal·la les dependències necessàries:
npm install --save typescript @types/node @types/react @types/react-dom @types/jest
  1. Canvia l'extensió dels fitxers .js a .tsx per als components de React i .ts per als altres fitxers.

  2. Crea un fitxer tsconfig.json a l'arrel del projecte amb la següent configuració bàsica:

{
  "compilerOptions": {
    "target": "es5",
    "lib": ["dom", "dom.iterable", "esnext"],
    "allowJs": true,
    "skipLibCheck": true,
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true,
    "strict": true,
    "forceConsistentCasingInFileNames": true,
    "noFallthroughCasesInSwitch": true,
    "module": "esnext",
    "moduleResolution": "node",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "noEmit": true,
    "jsx": "react-jsx"
  },
  "include": ["src"]
}

Tipar components de React

Components funcionals

Els components funcionals són els més comuns en React. Aquí tens un exemple de com tipar un component funcional amb props:

import React from 'react';

interface GreetingProps {
  name: string;
  age?: number; // Prop opcional
}

const Greeting: React.FC<GreetingProps> = ({ name, age }) => {
  return (
    <div>
      <h1>Hello, {name}!</h1>
      {age && <p>You are {age} years old.</p>}
    </div>
  );
};

export default Greeting;

Components de classe

Encara que els components de classe són menys comuns amb l'arribada dels hooks, és important saber com tipar-los:

import React, { Component } from 'react';

interface CounterProps {
  initialCount: number;
}

interface CounterState {
  count: number;
}

class Counter extends Component<CounterProps, CounterState> {
  constructor(props: CounterProps) {
    super(props);
    this.state = {
      count: props.initialCount
    };
  }

  increment = () => {
    this.setState({ count: this.state.count + 1 });
  };

  render() {
    return (
      <div>
        <p>Count: {this.state.count}</p>
        <button onClick={this.increment}>Increment</button>
      </div>
    );
  }
}

export default Counter;

Tipar hooks

useState

El hook useState pot ser tipat de la següent manera:

import React, { useState } from 'react';

const Counter: React.FC = () => {
  const [count, setCount] = useState<number>(0);

  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={() => setCount(count + 1)}>Increment</button>
    </div>
  );
};

export default Counter;

useEffect

El hook useEffect no necessita tipat explícit, però pots tipar les dades que utilitzes dins de l'efecte:

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

const DataFetcher: React.FC = () => {
  const [data, setData] = useState<string | null>(null);

  useEffect(() => {
    fetch('https://api.example.com/data')
      .then(response => response.json())
      .then(data => setData(data));
  }, []);

  return (
    <div>
      <p>Data: {data}</p>
    </div>
  );
};

export default DataFetcher;

Tipar context

Crear un context

import React, { createContext, useContext, useState } from 'react';

interface AuthContextType {
  user: string | null;
  login: (user: string) => void;
  logout: () => void;
}

const AuthContext = createContext<AuthContextType | undefined>(undefined);

const AuthProvider: React.FC = ({ children }) => {
  const [user, setUser] = useState<string | null>(null);

  const login = (user: string) => setUser(user);
  const logout = () => setUser(null);

  return (
    <AuthContext.Provider value={{ user, login, logout }}>
      {children}
    </AuthContext.Provider>
  );
};

const useAuth = () => {
  const context = useContext(AuthContext);
  if (!context) {
    throw new Error('useAuth must be used within an AuthProvider');
  }
  return context;
};

export { AuthProvider, useAuth };

Utilitzar el context

import React from 'react';
import { AuthProvider, useAuth } from './AuthContext';

const UserProfile: React.FC = () => {
  const { user, login, logout } = useAuth();

  return (
    <div>
      {user ? (
        <>
          <p>Welcome, {user}!</p>
          <button onClick={logout}>Logout</button>
        </>
      ) : (
        <button onClick={() => login('John Doe')}>Login</button>
      )}
    </div>
  );
};

const App: React.FC = () => {
  return (
    <AuthProvider>
      <UserProfile />
    </AuthProvider>
  );
};

export default App;

Exercicis pràctics

Exercici 1: Crear un component tipat

Crea un component funcional anomenat UserCard que accepti les següents props:

  • name (string)
  • email (string)
  • age (number, opcional)

El component ha de mostrar aquesta informació en un format adequat.

Solució

import React from 'react';

interface UserCardProps {
  name: string;
  email: string;
  age?: number;
}

const UserCard: React.FC<UserCardProps> = ({ name, email, age }) => {
  return (
    <div>
      <h2>{name}</h2>
      <p>Email: {email}</p>
      {age && <p>Age: {age}</p>}
    </div>
  );
};

export default UserCard;

Exercici 2: Utilitzar useState amb tipus personalitzats

Crea un component anomenat TodoList que utilitzi useState per gestionar una llista de tasques. Cada tasca ha de tenir un id (number) i un text (string).

Solució

import React, { useState } from 'react';

interface Todo {
  id: number;
  text: string;
}

const TodoList: React.FC = () => {
  const [todos, setTodos] = useState<Todo[]>([]);
  const [newTodo, setNewTodo] = useState<string>('');

  const addTodo = () => {
    const newTask: Todo = { id: Date.now(), text: newTodo };
    setTodos([...todos, newTask]);
    setNewTodo('');
  };

  return (
    <div>
      <input
        type="text"
        value={newTodo}
        onChange={(e) => setNewTodo(e.target.value)}
      />
      <button onClick={addTodo}>Add Todo</button>
      <ul>
        {todos.map((todo) => (
          <li key={todo.id}>{todo.text}</li>
        ))}
      </ul>
    </div>
  );
};

export default TodoList;

Conclusió

Integrar TypeScript en un projecte de React pot millorar significativament la qualitat del codi i la productivitat del desenvolupador. Hem après com configurar TypeScript en un projecte de React, com tipar components funcionals i de classe, com utilitzar hooks amb tipus i com gestionar contextos amb TypeScript. Amb aquests coneixements, estàs preparat per començar a utilitzar TypeScript en els teus projectes de React i aprofitar els seus avantatges.

Curs de React

Mòdul 1: Introducció a React

Mòdul 2: Components de React

Mòdul 3: Treballar amb esdeveniments

Mòdul 4: Conceptes avançats de components

Mòdul 5: Hooks de React

Mòdul 6: Enrutament en React

Mòdul 7: Gestió de l'estat

Mòdul 8: Optimització del rendiment

Mòdul 9: Proves en React

Mòdul 10: Temes avançats

Mòdul 11: Projecte: Construir una aplicació completa

© Copyright 2024. Tots els drets reservats