Saltar al contingut

Component

Un component de React és una funció de TypeScript a la qual pots afegir TSX.

Crea un projecte amb Deno

Terminal window
$ bun create vite react-component --template react-swc-ts
Scaffolding project in /home/box/react-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>

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.

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.

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>
}

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:

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"/>
}

I ja tens un component completament reutilitzable:

export default function App() {
return (
<>
<Greeting name="Miquel" emoji="🧙‍♂️"/>
<Greeting name="Armengol"/>
<Greeting name="Nuria" emoji="🐱"/>
</>
)
}

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.

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.

App

Greeting

Greeting

Greeting

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ó.

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:

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>
)
}

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!

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:

Terminal window
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>
)
}

1.- DogCard

  • Crea un componente DogCard con las propiedades name,description e image?.
  • La propiedad image? tiene una imagen por defecto
  • Utiliza este componente para mostrar una colección de perros.

2.- Happy.tsx

  • Crea el fichero Happy.tsx con dos funciones con nombre: HappyName y HappyImage.
  • HappyName tiene una propiedad name y muestra el nombre de forma divertida.
  • HappyImage tiene una propiedad image y muestra la imagen de forma divertida.
  • El componente App tiene que utilizar los dos componentes de Happy.tsx

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.

El contingut d'aquest lloc web té llicència CC BY-NC-ND 4.0.

©2022-2025 xtec.dev