En aquest tema, aprendrem com integrar TypeScript amb React per crear aplicacions robustes i mantenibles. React és una biblioteca de JavaScript per construir interfícies d'usuari, i TypeScript ens ajuda a escriure codi més segur i previsible. Combinats, ens permeten desenvolupar aplicacions amb una millor experiència de desenvolupament i menys errors en temps d'execució.
Continguts
Configuració del Projecte
Creació del Projecte amb Create React App
El mètode més senzill per començar un projecte de React amb TypeScript és utilitzar Create React App. Executa la següent comanda per crear un nou projecte:
Això crearà una nova aplicació de React amb TypeScript ja configurat.
Configuració Manual
Si prefereixes configurar el projecte manualment, segueix aquests passos:
-
Inicialitza un nou projecte de React:
npx create-react-app my-app cd my-app
-
Instal·la les dependències de TypeScript:
npm install --save typescript @types/node @types/react @types/react-dom @types/jest
-
Crea un fitxer
tsconfig.json
:{ "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"] }
-
Renombra els fitxers
.js
a.tsx
:Renombra els fitxers de component de React de
.js
a.tsx
per indicar que contenen JSX i TypeScript.
Components amb TypeScript
Components Funcionals
Els components funcionals són la manera més comuna de crear components en React. Aquí tens un exemple d'un component funcional amb TypeScript:
import React from 'react'; interface GreetingProps { name: string; } const Greeting: React.FC<GreetingProps> = ({ name }) => { return <h1>Hello, {name}!</h1>; }; export default Greeting;
Components de Classe
Encara que els components funcionals són més comuns, també pots utilitzar components de classe amb TypeScript:
import React, { Component } from 'react'; interface GreetingProps { name: string; } class Greeting extends Component<GreetingProps> { render() { return <h1>Hello, {this.props.name}!</h1>; } } export default Greeting;
Propietats i Estats
Propietats (Props)
Les propietats es defineixen utilitzant interfícies. Aquí tens un exemple:
interface ButtonProps { label: string; onClick: () => void; } const Button: React.FC<ButtonProps> = ({ label, onClick }) => { return <button onClick={onClick}>{label}</button>; };
Estats (State)
Per gestionar l'estat en components de classe, utilitza el tipus State
:
interface CounterState { count: number; } class Counter extends Component<{}, CounterState> { state: CounterState = { count: 0 }; increment = () => { this.setState({ count: this.state.count + 1 }); }; render() { return ( <div> <p>Count: {this.state.count}</p> <button onClick={this.increment}>Increment</button> </div> ); } }
Refs i Context
Refs
Els refs es poden utilitzar per accedir directament a un element DOM o a un component fill:
import React, { useRef } from 'react'; const InputFocus: React.FC = () => { const inputRef = useRef<HTMLInputElement>(null); const focusInput = () => { inputRef.current?.focus(); }; return ( <div> <input ref={inputRef} type="text" /> <button onClick={focusInput}>Focus Input</button> </div> ); };
Context
El context permet passar dades a través de l'arbre de components sense haver de passar explícitament les propietats a cada nivell:
import React, { createContext, useContext } from 'react'; interface ThemeContextProps { theme: string; toggleTheme: () => void; } const ThemeContext = createContext<ThemeContextProps | undefined>(undefined); const ThemeProvider: React.FC = ({ children }) => { const [theme, setTheme] = React.useState('light'); const toggleTheme = () => { setTheme((prevTheme) => (prevTheme === 'light' ? 'dark' : 'light')); }; return ( <ThemeContext.Provider value={{ theme, toggleTheme }}> {children} </ThemeContext.Provider> ); }; const ThemedComponent: React.FC = () => { const context = useContext(ThemeContext); if (!context) { throw new Error('ThemedComponent must be used within a ThemeProvider'); } return ( <div style={{ background: context.theme === 'light' ? '#fff' : '#333', color: context.theme === 'light' ? '#000' : '#fff' }}> <p>The current theme is {context.theme}</p> <button onClick={context.toggleTheme}>Toggle Theme</button> </div> ); }; export { ThemeProvider, ThemedComponent };
Hooks amb TypeScript
useState
El hook useState
es pot utilitzar amb TypeScript 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> ); };
useEffect
El hook useEffect
es pot utilitzar per gestionar efectes secundaris:
import React, { useEffect, useState } 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>{data ? data : 'Loading...'}</div>; };
Exercicis Pràctics
Exercici 1: Crear un Component de Llista
Crea un component que mostri una llista d'elements. Cada element ha de tenir un nom i una descripció.
Solució
import React from 'react'; interface ListItem { name: string; description: string; } interface ListProps { items: ListItem[]; } const List: React.FC<ListProps> = ({ items }) => { return ( <ul> {items.map((item, index) => ( <li key={index}> <h3>{item.name}</h3> <p>{item.description}</p> </li> ))} </ul> ); }; export default List;
Exercici 2: Crear un Formulari amb Validació
Crea un formulari que permeti als usuaris introduir el seu nom i correu electrònic. Afegeix validació per assegurar-te que els camps no estiguin buits.
Solució
import React, { useState } from 'react'; interface FormState { name: string; email: string; } const Form: React.FC = () => { const [formState, setFormState] = useState<FormState>({ name: '', email: '' }); const [errors, setErrors] = useState<{ name?: string; email?: string }>({}); const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => { const { name, value } = e.target; setFormState({ ...formState, [name]: value }); }; const handleSubmit = (e: React.FormEvent) => { e.preventDefault(); const newErrors: { name?: string; email?: string } = {}; if (!formState.name) { newErrors.name = 'Name is required'; } if (!formState.email) { newErrors.email = 'Email is required'; } setErrors(newErrors); if (Object.keys(newErrors).length === 0) { console.log('Form submitted successfully', formState); } }; return ( <form onSubmit={handleSubmit}> <div> <label> Name: <input type="text" name="name" value={formState.name} onChange={handleChange} /> </label> {errors.name && <p>{errors.name}</p>} </div> <div> <label> Email: <input type="email" name="email" value={formState.email} onChange={handleChange} /> </label> {errors.email && <p>{errors.email}</p>} </div> <button type="submit">Submit</button> </form> ); }; export default Form;
Conclusió
En aquest tema, hem après com integrar TypeScript amb React per crear aplicacions més robustes i mantenibles. Hem vist com configurar un projecte, crear components, gestionar propietats i estats, utilitzar refs i context, i treballar amb hooks. També hem practicat amb exercicis per reforçar els conceptes apresos. Amb aquests coneixements, estàs preparat per desenvolupar aplicacions de React amb TypeScript de manera eficient i segura.
Curs de TypeScript
Mòdul 1: Introducció a TypeScript
- Què és TypeScript?
- Configuració de l'entorn de TypeScript
- Tipus bàsics
- Anotacions de tipus
- Compilació de TypeScript
Mòdul 2: Treballant amb Tipus
Mòdul 3: Tipus Avançats
Mòdul 4: Funcions i Mòduls
- Tipus de Funció
- Paràmetres Opcional i per Defecte
- Paràmetres Rest
- Mòduls i Espais de Noms
- Decoradors
Mòdul 5: Programació Asíncrona
Mòdul 6: Eines i Millors Pràctiques
- Linting i Formatació
- Proves de Codi TypeScript
- TypeScript amb Webpack
- TypeScript amb React
- Millors Pràctiques