Component
Introducció
Section titled “Introducció”Un component de React és una funció de TypeScript a la qual pots afegir {% link “/ts/react/tsx/” %}.
Crea un projecte amb {% link “/ts/bun/” %}
$ bun create vite react-component --template react-swc-tsScaffolding project in /home/box/react-component......
Component
Section titled “Component”Defineix el component Greeting
que és utilitzat pel component App
:
export default function App() { return <Greeting/>}
function Greeting() { return <p className="fs-3 p-4 border">Hello X</p>}
Els components de React són funcions regulars de TypeScript, però els seus noms han de començar amb lletra majúscula o no funcionaran!
El component Greeting
està nidat dins del component App
.
Pots afegir tants components Greeting
com vulguis dins del component App
:
export default function App() { return ( <> <Greeting /> <Greeting /> <Greeting /> </> )}
function Greeting() { return <p className="fs-3 m-2 p-2 border text-center">Hello X</p>}
Al final el que el navegador veu és això:
<p class="fs-3 m-2 p-2 border text-center">Hello X</p><p class="fs-3 m-2 p-2 border text-center">Hello X</p><p class="fs-3 m-2 p-2 border text-center">Hello X</p>
Nidar i organitzar components
Section titled “Nidar i organitzar components”Els components són funcions regulars de TypeScript, per això pots tenir múltiples components en el mateix arxiu.
Ja que els components Greeting
es renderitzen dins d’App
(fins i tot diverses vegades!) podem dir que App
és un component pare, que renderitza cada Greeting
com un «fill».
Aquesta és la part màgica de React: pots definir un component una vegada, i després utilitzar-lo en molts llocs i tantes vegades com vulguis.
{% panel ”⚠ Atención!” %}
Els components poden renderitzar altres components, però mai has de nidar les seves definicions:
export default function App() {
// 🔴 ¡Nunca definas un componente dentro de otro componente! function Greeting() { // ... } // ...}
El fragment de codi de dalt és molt lent i causa errors.
En el seu lloc, defineix cada component en el primer nivell:
export default function App() { // ...}
// ✅ Declara los componentes en el primer nivelfunction Greeting() { // ...}
{% endpanel %}
Propietats
Section titled “Propietats”Els components de React utilitzen props per comunicar-se entre ells. Cada component pare pot enviar informació als seus components fills mitjançant l’ús de props.
Les props són les dades que es passen a un element TSX.
Per exemple, className
, src
i alt
són algunes de les props que es poden passar a un element <img/>
:
export default function App() {
return ( <> <img className="img-fluid" src="https://shorturl.at/tQoUY" alt="Rough Collie" /> </> )}
Les props que pots utilitzar amb un element <img/>
estan predefinides (ReactDOM s’ajusta a l’estàndard HTML).
No obstant això, pots passar qualsevol prop als teus propis components per personalitzar-los.
Passar props a un component
Section titled “Passar props a un component”En aquest codi, el component App
no està passant cap prop al seu component fill, Greeting
:
export default function App() { return <Greeting/>}
function Greeting() { return <p className="fs-3 p-2"><span className="fs-1">🧔</span> Hello David!</p>}
{% panel %}
🧔 Hello David!
{% endpanel %}El més lògic seria que el component pare passés al component fill el nom i l’emoji.
Primer, passa les props name
i emoji
a l’element Greeting
.
export default function App() { return <Greeting name="Laura" emoji="👩🦰"/>}
El component Greeting
accepta aquestes props especificant els seus noms name
i emoji
separats per comes dins de ({
i })
:
function Greeting({name, emoji}: { name: string, emoji: string }) { return <p className="fs-3 p-2"><span className="fs-1">{emoji}</span> Hello {name}!</p>}
Ara el component Greeting
pot saludar correctament:
{% panel %}
👩🦰 Hello Laura!
{% endpanel %}Les props compleixen el mateix paper que els arguments d’una funció — de fet, les props són l’únic argument del teu component!
Les funcions dels components de React accepten un únic argument, un objecte props
:
function Greeting(props: { name: string, emoji: string }) { return <p className="fs-3 p-2"><span className="fs-1">{props.emoji}</span> Hello {props.name}!</p>}
En general, no necessites accedir a l’objecte complet de props
, per això pots desestructurar-lo en props individuals:
function Greeting({name, emoji}: { name: string, emoji: string }) { ...}
Aquesta sintaxi es coneix com a “desestructuració”.
Assignar un valor predeterminat per a una prop
Section titled “Assignar un valor predeterminat per a una prop”Si vols assignar un valor predeterminat per a una prop en cas que no s’especifiqui cap valor, pots fer-ho mitjançant la desestructuració col·locant =
seguit del valor predeterminat just després del paràmetre:
function Greeting({name, emoji = "👽"}: { name: string, emoji?: string }) { return <p className="fs-3 p-2"><span className="fs-1">{emoji}</span> Hello {name}!</p>}
Fixa’t que ara el tipus de props és { name: string, emoji?: string }
, emoji és opcional.
Ara, si renderitzes Greeting
sense la prop emoji
, el valor d’emoji
s’establirà automàticament a "👽"
.
export default function App() { return <Greeting name="Armengol"/>}
{% panel %}
👽 Hello Armengol!
{% endpanel %}I ja tens un component completament reutilitzable:
export default function App() { return ( <> <Greeting name="Miquel" emoji="🧙♂️"/> <Greeting name="Armengol"/> <Greeting name="Nuria" emoji="🐱"/> </> )}
{% panel %}
🧙♂️ Hello Miquel!
👽 Hello Armengol!
🐱 Hello Nuria!
Renderització
Section titled “Renderització”Una aplicació de React està formada per molts components nidats entre si.
React, com a framework d’UI, és independent de la plataforma, i una aplicació React es pot renderitzar a la web, la qual utilitza marcat HTML com les seves primitives, o podria renderitzar-se en una plataforma mòbil o d’escriptori, que podria utilitzar diferents primitives d’UI.
Estructura d’arbre
Section titled “Estructura d’arbre”Igual que els navegadors i les plataformes mòbils, React utilitza estructures d’arbre per gestionar i modelar la relació entre els components en una aplicació de React.
Una característica important dels components és la capacitat de compondre components d’altres components. En nidar components, tenim el concepte de components pare i fill, on cada component pare pot ser alhora un fill d’un altre component.
Quan renderitzem una aplicació de React, podem modelar aquesta relació en un arbre, conegut com l’arbre de renderització.
El node arrel en un arbre de renderització de React és el component arrel de l’aplicació. En aquest cas, el component arrel és App
i és el primer component que React renderitza. Cada fletxa en l’arbre apunta des d’un component pare cap a un component fill.
- L’arbre de renderització està compost únicament per components de React.
- Un arbre de renderització representa una única passada de renderització d’una aplicació de React.
- Amb renderització condicional, un component pare pot renderitzar diferents fills depenent de les dades passades.
- L’arbre de renderització pot ser diferent per a cada passada de renderització.
Components purs
Section titled “Components purs”React està dissenyat amb la suposició que cada component que escrius és una funció pura.
Això significa que un component sempre ha de retornar el mateix TSX donades les mateixes entrades, i no canviar qualsevol objecte o variable que existís abans de renderitzar.
A continuació tens un component que trenca aquesta regla:
let evil = "🤗"
export default function App() { return ( <div className="container"> <Greeting name="Miquel" emoji="🧙♂️"/> <Greeting name="Armengol"/> <Greeting name="Nuria" emoji="🐱"/> </div> )}
function Greeting({name, emoji = "👽"}: { name: string, emoji?: string }) { evil = `${evil} ${emoji}` return <p className="fs-4 p-2"><span className="fs-2">{evil}</span> Hello {name}!</p>}
Pots veure que els emojis apareixen duplicats:
{% panel %}
🤗 🧙♂️ 🧙♂️ Hello Miquel!
🤗 🧙♂️ 🧙♂️ 👽 👽 Hello Armengol!
🤗 🧙♂️ 🧙♂️ 👽 👽 🐱 🐱 Hello Nuria!
I més important, si canvies l’ordre dels Greeting
, retornen un TSX diferent:
export default function App() { return ( <div className="container"> <Greeting name="Nuria" emoji="🐱"/> <Greeting name="Miquel" emoji="🧙♂️"/> <Greeting name="Armengol"/> </div> )}
{% panel %}
🤗 🐱 🐱 Hello Nuria!
🤗 🐱 🐱 🧙♂️ 🧙♂️ Hello Miquel!
🤗 🐱 🐱 🧙♂️ 🧙♂️ 👽 👽 Hello Armengol!
Importar y exportar componentes
Section titled “Importar y exportar componentes”La magia de los componentes reside en su reusabilidad: puedes crear componentes que se componen a su vez de otros componentes.
Pero mientras anidas más y más componentes, a menudo tiene sentido comenzar a separarlos en diferentes archivos.
Crea un fichero src/Greeting.tsx
:
export default function Greeting({name, emoji = "👽"}: { name: string, emoji?: string }) { return <p className="fs-4 p-2"><span className="fs-2">{emoji}</span> Hello {name}!</p>}
Importa Greeting
con un import por defecto desde Greeting.tsx
:
import Greeting from './Greeting.tsx'
export default function App() { return ( <div className="container"> <Greeting name="Nuria" emoji="🐱"/> <Greeting name="Armengol"/> </div> )}
Si quieres puedes canviar el nombre del componente cuando lo utilizas:
import Saluto from './Greeting.tsx'
export default function App() { return ( <div className="container"> <Saluto name="Nuria" emoji="🐱"/> <Saluto name="Armengol"/> </div> )}
En lugar de utilizar un export por defecto puedes utilitzar un export por nombre (sin la palabra clave default
):
export function Greeting({name, emoji = "👽"}: { name: string, emoji?: string }) { return <p className="fs-4 p-2"><span className="fs-2">{emoji}</span> Hello {name}!</p>}
Ahora tienes que importar el componente Greeting
usando un import con nombre (con llaves):
import {Greeting} from './Greeting.tsx'
export default function App() { return ( <div className="container"> <Greeting name="Nuria" emoji="🐱"/> <Greeting name="Armengol"/> </div> )}
¡Un archivo solo puede contener un export por defecto, pero puede tener múltiples exports con nombre!
Librerias
Section titled “Librerias”Hay muchas librerías de react que puedes utilizar: Awesome React Components.
Pigeon Maps - Docs te proporciona un componente que te permite añadir mapas sin dependencias externas.
Instala la librería pigeon-maps
:
bun add pigeon-maps
A continuación tenemos un mapa de Barcelona (Spain) con un marcador en la Sagrada Familia.
import {Map, Marker} from "pigeon-maps"
export default function App() { return ( <div className="container p-5"> <Map height={600} defaultCenter={[41.40369, 2.17433]} defaultZoom={14}> <Marker width={50} anchor={[41.40369, 2.17433]}/> </Map> </div> )}
{% panel %}
Actividades
Section titled “Actividades”1.- DogCard
- Crea un componente
DogCard
con las propiedadesname
,description
eimage?
. - La propiedad
image?
tiene una imagen por defecto - Utiliza este componente para mostrar una colección de perros.
{% panel %}

Rough Collie
A dog breed that's well-known for herding and protecting abilities, rough collie dogs are described as strong, loyal, affectionate, responsive, and fast.

Affenpinscher
Affenpinscher dogs are best known for their expressive face, with a short muzzle and dark, round eyes that give them an appearance not unlike a monkey.
{% sol %}
export default function App() {
return ( <div className="container"> <div className="row p-2 justify-content-evenly"> <div className={"col-3"}> <DogCard name="Rough Collie" description="A dog breed that's well-known for herding and protecting abilities, rough collie dogs are described as strong, loyal, affectionate, responsive, and fast." image="https://upload.wikimedia.org/wikipedia/commons/thumb/6/65/Rough-Collie-japan08_%28cropped%29.jpg/1200px-Rough-Collie-japan08_%28cropped%29.jpg"/> </div> <div className="col-3"> <DogCard name="Affenpinscher" description="Affenpinscher dogs are best known for their expressive face, with a short muzzle and dark, round eyes that give them an appearance not unlike a monkey."/> </div> </div> </div> )}
function DogCard({name, description, image = "https://d29fhpw069ctt2.cloudfront.net/icon/image/39024/preview.png"}: { name: string, description: string, image?: string}) { return ( <div className="card"> <img className="card-img-top img-fluid" src={image} alt={name}/> <div className="card-body"> <h5 className="card-title">{name}</h5> <p className="card-text">{description}</p> </div> </div> )}
{% endsol %}
2.- Happy.tsx
- Crea el fichero
Happy.tsx
con dos funciones con nombre:HappyName
yHappyImage
. HappyName
tiene una propiedadname
y muestra el nombre de forma divertida.HappyImage
tiene una propiedadimage
y muestra la imagen de forma divertida.- El componente
App
tiene que utilizar los dos componentes deHappy.tsx
{% panel %}

{% sol %}
App.tsx
import {HappyName,HappyImage} from "./Happy.tsx";
export default function App() { return ( <div className="container p-5"> <HappyName name="Laura"/> <HappyImage image="https://upload.wikimedia.org/wikipedia/commons/thumb/b/bc/Laura_Dern_Deauville_2017.jpg/440px-Laura_Dern_Deauville_2017.jpg"/> </div> )}
Happy.tsx
export function HappyName({name}: { name: string }) { return <span className={"fs-3 border border-5 border-danger rounded-pill m-2 p-2 ps-5 pe-5 fw-semibold font-monospace"}>{name}</span>}
export function HappyImage({image}: { image: string }) { return <img src={image} className={"img-fluid img-thumbnail w-25 p-2 border border-5 border-primary"}/>}
{% endsol %}
3.- Pigeon Maps
- Busca en Internet las coordendas geográficas y un GeoJSON de París.
- Crea un mapa de París y alrededores marcando los límites de París.
{% panel %}
El contingut d'aquest lloc web té llicència CC BY-NC-ND 4.0.
©2022-2025 xtec.dev