#CestFacile :Vérification de types (feat PropTypes)

Jusqu’ici c’était un peu la récrée.

On a écrit quelques tests unitaires pour faire bonne figure (et surtout pour se familiariser avec Enzyme, Jest et Chai), mais on a toujours pas abordé la vérification de types, ne serait-ce qu’avec les prop-types.

C’est le moment de passer du temps sur le sujet.

Vérification de types

L’idée autour de la vérification de types, c’est de faire plaisir aux développeurs Java c’est notamment de documenter par le code les types de valeurs attendues dans vos props, et d’éviter les effets de bord lorsqu’un collègue commence à modifier votre boulot.

C’est très utile, car ça permet en bout de course de vous épargner quantité de bugs qui pourraient vous amener à vous tirer les cheveux (du genre, allez, au pif, passer un int sous forme de string et faire une addition dessus).

On va reprendre nos containers et composants et ajouter dans un premier temps nos PropTypes.

PropTypes

Depuis quelques temps, c’est devenu une librairie indépendante de React, il faut donc l’installer :

yarn add prop-types

On va commencer par quelque chose de simple, dans notre container Login, on passe en props une partie de notre state (auth) :

const initialState = {
 stuff: [],
 auth: {
   loading: false,
   logged: false,
 }
}

loading et logged sont deux booléens au sein d’un objet (auth)

const mapStateToProps = ({auth}) => ({
  auth
})

Tout ce qu’on a à faire, c’est importer PropTypes :

import PropTypes from 'prop-types';

Puis à déclarer :

Login.propTypes = {
 auth: PropTypes.shape({
   loading: PropTypes.string.isRequired,
   logged: PropTypes.bool.isRequired,
 })
}

Ici, on déclare les propriétés de l’objet auth avec PropTypes.shape(). On en profite pour déclarer que ces props sont obligatoires.

Vous trouverez toute la liste des types sur le repo officiel :

https://github.com/facebook/prop-types

Ho ! Et non, vous ne rêvez pas, j’ai bien fait une erreur.

C’est volontaire et c’est pour illustrer ceci :

La console nous renvoi une belle erreur. PropTypes a détecté que la prop est de type boolean et non pas string.

SHAME !

via GIPHY

Corrigeons le tir :

Login.propTypes = {
 auth: PropTypes.shape({
   loading: PropTypes.bool.isRequired,
   logged: PropTypes.bool.isRequired,
 })
}

Ca va mieux ! Du moins la console arrête de nous crier dessus.

Mais… attendez une seconde, ce ne sont pas les seules props que l’on balance à notre container :

const mapDispatchToProps = (dispatch) => ({
  actions: bindActionCreators(authActions, dispatch)
})

On a une prop « actions » qui contient les actions issues de ./src/Services/Auth/actions. On a tout intérêt à déclarer le type également.

Dans la mesure où la prop actions est bind aux actions via bindActionCreators, on peut se contenter de déclarer que actions est un objet, et qu’il est obligatoire :

Login.propTypes = {
 auth: PropTypes.shape({
   loading: PropTypes.bool.isRequired,
   logged: PropTypes.bool.isRequired,
 }),
 actions: PropTypes.object.isRequired,
}

La console ne vous hurlera pas dessus, mais on pourrait aussi faire quelque chose dans ce style :

Login.propTypes = {
 auth: PropTypes.shape({
   loading: PropTypes.bool.isRequired,
   logged: PropTypes.bool.isRequired,
 }),
 actions: PropTypes.shape({
   login: PropTypes.func.isRequired, 
   loggedIn: PropTypes.func.isRequired
 })
}

Plutôt simple, on peut appliquer la même logique pour nos autres composants.

Bien entendu il y a une meilleure façon de procéder lorsqu’il s’agit de validation de types. Les PropTypes ont un défaut majeur : elles fonctionnent au runtime, ce qui signifie que l’on constate qu’il y a un problème bien trop tard dans l’écriture du code.

Flow répond notamment (mais pas que, loin de là) à cette problématique et permet de choper les erreurs directement dans un IDE (Atom, Visual Studio Code…).

On parlera de Flow bien plus tard. Promis.

Le code est dispo ici :

https://github.com/GregoryBabonaux/react-c-est-facile/tree/6f7b5f028640600c153890c0e54cdc2447459e8c

 

 

 

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *