Props
Componenten staan meestal niet zomaar op zichzelf. Vaak hebben ze data nodig dat van buitenaf komt. Afhankelijk van welke data er doorgegeven wordt aan het component zal het zich anders gedragen. Deze data worden doorgeven aan der hand van properties (of props in het kort).
String doorgeven als property
Stel dat je een component hebt dat een gekleurd vierkant toont:
const ColorSquare = () => {
return <div style={{width: 100, height: 100, backgroundColor: 'red'}}/>
}
const App = () => {
return <ColorSquare/>
}
Willen we het ColorSquare
component ook gebruiken voor blauwe vierkanten moeten we een nieuwe property: color
aanmaken:
interface ColorSquareProps {
color: string
}
const ColorSquare = (props: ColorSquareProps) => {
return <div style={{width: 100, height: 100, backgroundColor: props.color}}/>
}
const App = () => {
return (
<>
<ColorSquare color="blue"/>
<ColorSquare color="red"/>
</>
);
}
Hier zie je een aantal dingen:
- ColorSquare krijgt een argument:
props
bij met het typeColorSquareProps
. Hier zitten alle properties die worden doorgegeven aan deColorSquare
component. - In TypeScript voorzien we altijd types voor elk object, dit is ook zo voor het props object.
- We halen de
color
property uit het props object aan de hand van de dot notatie. - Properties worden doorgegeven zoals elk HTML attribuut.
Expressies doorgeven als property
We kunnen ook de grootte van onze ColorSquare doorgeven aan de hand van props:
interface ColorSquareProps {
color: string;
size: number
}
const ColorSquare = (props: ColorSquareProps) => {
return <div style={{width: props.size, height: props.size, backgroundColor: props.color}}/>
}
const App = () => {
return <ColorSquare color="blue" size={200}/>
}
Belangrijk hier is dat getallen doorgegeven worden tussen accolades en niet tussen dubbele quotes.
Dit geldt ook voor alle andere soorten expressies. Wil je bijvoorbeeld werken met variabelen dan moeten deze ook tussen accolades staan.
const App = () => {
let color: string = "blue";
let size: number = 200;
return <ColorSquare color={color} size={size}/>
}
Destructuring props
Om je code te vereenvoudigen kan je gebruik maken van object destructuring om de properties al uit het props object te halen.
const ColorSquare = ({size, color}: ColorSquareProps) => {
return <div style={{width: size, height: size, backgroundColor: color}}/>
}
Op deze manier moeten we dus niet elke keer de property uit het props
object halen.
Interface vervangen door type alias
We hebben hiervoor aangegeven dat je altijd een interface moet aanmaken voor elk component. We kunnen dit ook in de functie declaratie zelf doen.
const ColorSquare = ({size, color}: {color: string, size: number}) => {
return <div style={{width: size, height: size, backgroundColor: color}}/>
}
H2O Game Shop
We grijpen nu even terug naar ons voorbeeld van de games winkel die we aan het opbouwen zijn.
Op dit moment hebben we nog altijd onze data die we gebruiken voor onze lijst in een globale variabele gestoken in de huidige applicatie. Het is uiteraard niet houdbaar om alles in globale variabelen te steken en deze zo te delen onder verschillende componenten. De juiste manier om dit te doen in React is deze lijst of andere variabelen door te geven als props of properties. We geven dus informatie door van het ene component naar de andere.
Voordat we props voor de eerste keer gaan gebruiken in onze applicatie gaan we eerst onze lijst van games verplaatsen naar het App component zelf.
const App = () => {
const games : Game[] = [
//...
];
return (
<div>
<h1>Welcome to the H2O Game shop</h1>
<List/>
</div>
);
}
Nu geeft uiteraard de List component een foutmelding omdat de games variabele niet meer globaal staat en dit component dus geen toegang heeft tot deze lijst. We gaan dit oplossen door de games variabele door te geven aan de List component aan de hand van een games
property.
interface ListProps {
games: Game[]
}
const List = ({games}: ListProps) => {
return (
<div>
{games.map((game: Game) => {
return <React.Fragment key={game.id}>
<h2>{game.name} ({game.releaseYear})</h2>
<p>Aantal keer verkocht: {game.sales}</p>
</React.Fragment>
})}
</div>
);
}
const App = () => {
const games : Game[] = [
//...
];
return (
<div>
<h1>Welcome to the H2O Game shop</h1>
<List games={games}/>
</div>
);
}
Nu kunnen we onze kennis over props gaan gebruiken om onze List component nog verder op te splitsen in kleinere componenten als we dit willen. Zo kunnen we een ListItem introduceren die verantwoordelijk is voor het tonen van 1 item van de lijst.
interface ListItemProps {
game: Game
}
const ListItem = ({game} : ListItemProps) => {
return (
<React.Fragment>
<h2>{game.name} ({game.releaseYear})</h2>
<p>Aantal keer verkocht: {game.sales}</p>
</React.Fragment>
)
}
const List = ({games}: ListProps) => {
return (
<div>
{games.map((game: Game) => {
return <ListItem key={game.id} game={game}/>
})}
</div>
);
}
Het gebeurt vaak dat props doorheen meerdere componenten worden doorgegeven. Indien je componenten structuur dieper en dieper wordt, wordt het ook altijd maar minder praktisch om dingen te gaan blijven doorgeven aan de hand van properties. We zien later nog hoe we dit probleem kunnen oplossen.