Découvrez le typage
Les PropTypes sont une des méthodes les plus répandues pour sécuriser le type des props que reçoivent vos composants.
Le type ? Mais qu'est-ce que c'est ?
Je vous avais déjà parlé de types dans le premier cours. Si si, souvenez-vous du chapitre "Réutilisez vos composants avec les props" ... 💭
En termes de typage, le typage de JavaScript est considéré comme "faible" : JS fonctionne sur du typage dynamique et n'assure pas de type safety. Cela veut dire que lorsqu'on déclare une nouvelle variable, le développeur ou la développeuse ne précise pas de quel type sera la nouvelle variable, le code s'adapte à la volée, et on peut tout à fait changer le type d'une variable.
En JS, je peux totalement faire :
let maVariable = 42
maVariable = "quarante trois"
Alors que dans un certain nombre d'autres langages, ce n'est pas du tout possible. Typiquement, en C, je dois préciser le type dès la déclaration et il ne change pas. Le typage est alors qualifié de "statique". Ici, maVariable
est un integer
:
int maVariable;
maVariable = 42; // Pas de souci ici
maVariable = "Quarante trois"; // Ce code ne compilera pas !
Les choses sont donc bien plus flexibles en JavaScript.
Mais ne vous réjouissez pas trop vite, cette flexibilité peut aussi causer votre perte. ☠️ En effet, des bugs sont vite arrivés en JavaScript, surtout lorsque vous collaborez en équipe !
C'est pourquoi il existe des outils pour assurer ses arrières, tels que les PropTypes. 🤩
Installez PropTypes
La bibliothèque PropTypes vous permet de déclarer le type des props qui est attendu lorsque vous les récupérez dans vos composants, et de déclencher un warning si ça ne correspond pas. Bien pratique !
Comme d'habitude, pour installer la bibliothèque PropTypes, il vous suffit de lancer la commande yarn add prop-types
.
Profitons-en pour mettre les propTypes
en pratique dans notre application Shiny Agency !
Nous allons dès maintenant coder la base des Card
dans la page /freelances
.
Dans le dossier /components
, on vient créer un nouveau dossier /Card
dans lequel vous pouvez créer un fichier index.jsx
. Vous pouvez y coller le code suivant :
function Card({ label, title, picture }) {
return (
<div style={{ display: 'flex', flexDirection: 'column', padding: 15 }}>
<span>{label}</span>
<img src={picture} alt="freelance" height={80} width={80} />
<span>{title}</span>
</div>
)
}
export default Card
Ce composant récupère 3 props : label
, title
et picture
. J'ai également ajouté quelques propriétés de style pour que le tout soit plus visible.
Nous allons utiliser les Card
dans notre fichier Freelances/index.jsx
. Comme nous n'avons pas encore récupéré les datas que nous afficherons (un peu de patience, jeune padawan, nous le ferons dans la prochaine partie), nous allons créer un tableau d'objets nous-mêmes, qu'on déclare dans /pages/Freelances/index.jsx
:
import DefaultPicture from '../../assets/profile.png'
const freelanceProfiles = [
{
name: 'Jane Doe',
jobTitle: 'Devops',
picture: DefaultPicture,
},
{
name: 'John Doe',
jobTitle: 'Developpeur frontend',
picture: DefaultPicture,
},
{
name: 'Jeanne Biche',
jobTitle: 'Développeuse Fullstack',
picture: DefaultPicture,
},
]
Ici, on utilise une photo de profil vide standard qu'on a mise dans un dossier /assets
. Nous pouvons mapper ce tableau pour afficher le composant Card
(si vous avez un doute sur ce procédé, vous pouvez jeter un œil au chapitre "Gagnez en temps et en efficacité grâce aux listes et aux conditions" qui en parle dans le cours précédent) :
function Freelances() {
return (
<div>
<h1>Freelances 👩💻👨💻👩💻</h1>
{freelanceProfiles.map((profile, index) => (
<Card
key={`${profile.name}-${index}`}
label={profile.jobTitle}
picture={profile.picture}
title={profile.name}
/>
))}
</div>
)
}
Nous avons tout ce qu'il nous faut ! Sécurisons donc les props de Card
avec les propTypes ! 💪
Card
récupère 3 props, label
, title
et picture
. On va donc importer PropTypes
depuis la bibliothèque et utiliser Card.propTypes
pour préciser les types de chacune des propriétés.
import PropTypes from 'prop-types'
function Card({ label, title, picture }) {
return (
<div style={{ display: 'flex', flexDirection: 'column', padding: 15 }}>
<span>{label}</span>
<img src={picture} alt="freelance" height={80} width={80} />
<span>{title}</span>
</div>
)
}
Card.propTypes = {
label: PropTypes.string,
title: PropTypes.string,
picture: PropTypes.string,
}
export default Card
Vous pouvez essayer dès maintenant de passer une prop dont le type n'est pas string
, pour voir. Dans freelances/index.jsx
:
{freelanceProfiles.map((profile, index) => (
<Card
key={`${profile.name}-${index}`}
label={profile.jobTitle}
picture={profile.picture}
title={42}
/>
))}
Bravo à vous, vous venez de sécuriser votre composant Card
à l'aide des propTypes. 🎉
Mais je ne vous ai pas tout montré : vous pouvez même préciser si une prop est requise ou non !
Exigez une prop
Il est très simple de préciser qu'une prop est requise pour le bon fonctionnement de l'application. Pour cela, il suffit d'ajouter isRequired
à la suite du type déclaré.
Par exemple, toujours pour Card
, si on fait :
Card.propTypes = {
label: PropTypes.string,
title: PropTypes.string.isRequired,
picture: PropTypes.string
}
… et qu'on omet de déclarer la prop title
, ça nous donne :
Et voilà, vous avez réussi à "exiger" une prop avec .isRequired
!
Je voulais vous montrer une dernière chose en lien avec les propTypes : comment définir une prop par défaut.
Définissez des props par défaut
Bon, si vous avez suivi le cours précédent, vous avez déjà vu comment définir des props par défaut avec la déstructuration. Mais nous allons voir comment le faire de manière plus formelle : nous allons utiliser defaultProps
. Dans l'exemple précédent, au lieu de déclencher une erreur pour notre propriété manquante (alors qu'on avait précisé isRequired
), nous aurions pu aussi déclarer une propriété par défaut.
Il est possible d'assigner une valeur à title
directement dans la déstructuration, comme ici :
function Card({ label, title = 'Mon titre par défaut', picture })
Mais cette syntaxe déclenche malgré tout une erreur de PropType
. Dans ce cas, la meilleure manière est d'avoir recours à defaultProps
. Juste en dessous de Card.propTypes
, nous déclarons un objet Card.defaultProps
:
Card.defaultProps = {
title: 'Mon titre par défaut',
}
Exercez-vous
Vous avez appris à utiliser les PropTypes pour sécuriser votre application : félicitations à vous ! 💪 Le temps est maintenant venu de mettre vos connaissances en pratique.
Pour cela, vous trouverez le code pour débuter l’exercice sur la branche P1C3-begin
. Ici, vous devrez :
Ajouter
isRequired
à toutes les props deCard
.Préciser une prop par défaut pour
title
,label
etpicture
.
Les props par défaut de title
et label
sont une string vide. La prop par défaut de picture
est DefaultPicture
, que nous avons utilisée dans ce chapitre. Vous pouvez supprimer les props inutiles.
À l’avenir, vous devrez typer toutes les props de vos composants dans notre application.
Comme d’habitude, la solution se trouve sur la branche P1C3-solution
.
En résumé
Le typage de JavaScript est considéré comme faible : le type des variables est défini de manière dynamique à la volée, en fonction des valeurs assignées, et il peut changer à tout moment (pas de type safety).
La bibliothèque
prop-types
permet de sécuriser vos props en déclarant un type pour chaque prop.Vous pouvez “exiger” une prop dans un composant avec
isRequired
.Pour éviter les erreurs, vous pouvez définir une propriété par défaut avec
defaultProps
.
La base de votre application commence vraiment à être robuste. 💪 Mais vous l’aurez sûrement remarqué : elle n’a pas de style. Pas de panique, nous allons styliser tout ça dès le prochain chapitre avec Styled Components. 💅