Fermer

février 28, 2019

TypeScript et React, BFF


TypeScript et React forment un couple de plus en plus commun. Apprenez à vous familiariser avec TypeScript pour votre prochain projet React

TypeScript est de plus en plus en train de devenir un choix courant lors du démarrage d’un nouveau projet React. Il est déjà utilisé dans des projets de grande envergure, tels que MobX Apollo Client et même VS Code lui-même, qui prend en charge étonnamment TypeScript. Cela a du sens puisque TypeScript et VS Code sont créés par Microsoft! Heureusement, il est très facile à utiliser maintenant sur un nouveau projet create-react-app Gatsby ou Next.js .

Dans cet article, nous ' Nous verrons comment utiliser TS sur les projets susmentionnés, ainsi que quelques-uns des scénarios les plus courants que vous rencontrerez lors de l’utilisation de TS pour votre projet React. Les trois exemples sont disponibles ici .

TS et create-react-app

À partir de la version 2.1.0, create-react-app fournit une intégration TypeScript . dès la sortie de la boîte. Après avoir généré une nouvelle application ( create-react-app nom-app ), vous devrez ajouter quelques bibliothèques qui permettront à TypeScript de fonctionner et fourniront également les types utilisés par React, ReactDOM et. Jest.

 fil add typescript @ types / noeud @ types / réagir @ types / réagir-dom @ types / jest

Vous pouvez maintenant renommer vos fichiers composants se terminant par js ou jsx en l'extension TypeScript tsx . Lors du démarrage de votre application, la première fois qu'il détecte un fichier tsx il génère automatiquement un fichier tsconfig.json utilisé pour configurer tous les aspects de TypeScript.

Nous couvrons ce que ce fichier de configuration est un peu plus bas, alors ne vous inquiétez pas pour les détails maintenant. Le fichier tsconfig.json généré par create-react-app se présente comme suit:

 {
   "compilerOptions" :   {
     "target"  :   "es5" 
     "allowJs" :   true 
     "skipLibCheck" :   false  "esModuleInterop" :   true 
     "allowSyntheticDefaultImports" :   true 
     "strict" :   , 
     "forceConsistentCasistentCasingInFile Names" :   true 
     "module" :   "esnext" 
     "moduleResolution" :  19659015] "noeud" 
     "resolJsonModule" :   true 
     "isolatedModules" :   true 
    
     ":   true 
    " jsx ":  " préserver "
  } 
  " inclure ":   [ "src" ] 
} 

Assez drôle, le fichier App.js renommé en App.tsx fonctionne sans modification particulière. Etant donné que nous n'avons reçu aucune variable, fonction ou même accessoire défini par l'utilisateur, aucune information supplémentaire ne doit être fournie pour que TypeScript fonctionne avec ce composant.

TS et Next.js

.js app déjà configuré ajoutez le paquet @ zeit / next-typescript avec la commande yarn add @ zeit / next-typus .

nous pouvons créer un fichier next.config.js à la racine de notre projet, principalement responsable de la modification des aspects du processus de construction de Next.js, notamment de la configuration de la WebPack. Notez que ce fichier ne peut pas avoir une extension .ts et ne tourne pas par babel lui-même, vous ne pouvez donc utiliser que les fonctionnalités de langage trouvées dans votre environnement de noeud.

 const  withTypeScript  =   require  ( "@ zeit / next-manuscrit" ) ; 
module .  exports  =   avec TypeScript  () ; 

Créez un fichier .babelrc (dans la racine du projet):

 {
   "presets" :   [ "next / babel"  ,   "@ zeit / next-typescript / babel" ] 
} 

Créez un fichier tsconfig.json (dans la racine du projet):

 {
   "compilerOptions" :   {
     "allowJs" :   true 
     "allowSyntheticDefaultImports" :   true 
     "baseUrl" :   "." 
     " jsx ":  " conserve "
    " lib ":   " dom " " es2017 "] 
     "module" :   "esnext" 
     "moduleResolution" :   "noeud" 
     "noEmit" :   true 
     "noUnusedLocals" :   true 
     "noUnusedParameters" :   true 
     ] "preserveConstEnums" :   true 
     "removeComments" :   true 
     "skipLibCheck" :   true  ]
     "sourceMap" :   true 
     "strict" :   true 
     "cible" :   "esnext" 
  } 
} 

Je recommanderais ensuite d'ajouter le fil add @ types / react @ types / react-dom @ types / next afin que notre application ait accès aux types fournis par ces bibliothèques. Nous pouvons maintenant renommer notre page index.js en index.tsx . Nous sommes maintenant prêts à poursuivre le développement d'applications à l'aide de TypeScript.

TS et Gatsby

Nous allons commencer par créer une nouvelle application Gatsby le nouveau nom de l'application gatsby . Après cela, il est temps d'installer un plugin qui gère TypeScript pour vous: fil add gatsby-plugin-typescript

Bien que cela ne semble pas être nécessaire, créons a tsconfig.json . Nous le prendrons dans l'exemple de Gatsby TypeScript .

 {
   "include" :   [ "./ src / ** / *" [19659011]] 
   "compilerOptions" :   {
     "target" :   "esnext" 
     "module" :   "commonjs" 
     "lib" :    "dom"   "es2017" ] 
     ] "jsx" :   "réagir" 
     "strict" :   true 
     "esModuleInterop" :   
     "expérimentalDecorators" :   true 
     "emitDecoratorMetadata" :   true 
     "noEmit" :   true 
     "skipLibCheck" :   true 
  } 
} 

Nous pouvons maintenant renommer src / pages / index.js en index.tsx et TypeScript travaille sur notre projet Gatsby… ou du moins nous le faisons presque! Dans la mesure où un projet Gatsby par défaut contient quelques composants tels que Header Image et Layout il est nécessaire de les convertir en .tsx [ce qui soulève quelques autres problèmes liés à la gestion des accessoires dans TS, ou à d'autres packages externes qui pourraient ne pas être livrés immédiatement avec le support TS.

Nous allons rapidement aborder quelques paramètres dans Les fichiers tsconfig.json revêtent une importance particulière et permettent de mieux comprendre comment nous pouvons aller au-delà de la configuration TS en utilisant et en définissant les types sur nos projets React. 'ai déjà vu le fichier tsconfig.json à quelques reprises, mais de quoi s'agit-il? Comme son nom l'indique, il vous permet de configurer les options du compilateur TypeScript. Voici les options du compilateur TypeScript par défaut qui seront utilisées si aucun fichier tsconfig.json n'est fourni.

Le paramètre jsx utilisé en mode de réaction L’application dont la cible est le Web aura l’une des deux valeurs suivantes: vous choisirez de réagir s’il s’agit de la dernière étape de la compilation, ce qui signifie qu’elle sera chargée de convertir JSX en JS ou . préserver si vous voulez que Babel convertisse JSX en JS

strict est généralement mieux réglé sur true (même si sa valeur par défaut est false), en particulier sur nouveaux projets, pour aider à appliquer les meilleures pratiques et l'utilisation des TS.

La plupart des autres options vous appartiennent et je ne m'éloignerai pas trop de la configuration recommandée définie par le cadre que vous utilisez, à moins que vous n'ayez une réelle

Notions de base de TS

Si vous n’avez jamais travaillé avec TS auparavant, je vous recommanderais d’abord de leur tutoriel TypeScript en 5 minutes . Regardons quelques-uns des types de base sans trop entrer dans les détails.

 let  aNumber :  numéro  =   5 ; 
 let  aString :  string  =   "Bonjour" ; 
 let  aBool : [1945911].   true ; 
 // On peut dire que les âges constitueront un tableau de «nombre», en ajoutant «[]» à la fin de notre type numérique. 
 Let  âges :  numéro  []   =   [ 1   2   3 ] [19659011]; 

Vous remarquerez que cela ressemble en gros à JavaScript, mais après le nom de la variable, il y a : sometype sometype est l'un des types disponibles fournis par TS ou, comme vous verrez ci-dessous, créé par nos soins.

Avec les fonctions nous avons pour tâche de fournir les types du ou des arguments, ainsi que le type renvoyé par une fonction. 19659261] // reçoit 2 arguments de nombre, retourne un nombre
let add = ( num1 : numéro num2 ]: numéro ) : numéro => num1 + num2 ;
laissez réponse = add ( 5 6 ) ;
console . log ( response ) ;

La ​​beauté de TypeScript réside dans le fait qu'il est souvent capable de comprendre le type d'une variable. Dans VS Code, si vous survolez la variable avec la réponse il affichera let réponse: numéro car il sait que la valeur sera un nombre basé sur la déclaration de add qui renvoie un nombre

Dans JS, il est courant de recevoir des réponses JSON ou de travailler avec des objets ayant une certaine forme. Les interfaces constituent l'outil permettant de définir ici à quoi ressemblent les données:

 interface   Person   {
  nom :  chaîne ; 
  âge ? :  numéro ; 
} 

 const   register   =   personne  personne :  personne )   =>   {
  console .  log  ( ` $ { personne .  nom }   a été enregistré» . ] ) ; 
} ; 

 registre  ( { nom :   "Marian"  }  ) ; 
 registre  ( { nom :   "Leigh"  âge :   76  . } ) ; 

Nous disons ici qu'une personne peut avoir deux propriétés: name qui est une chaîne, et éventuellement age qui, lorsqu'il est présent, est un nombre. Le ?: indique que cette propriété ne peut pas être présente sur une personne. Lorsque vous survolez la propriété de l’âge vous verrez le code de VS vous dire qu’il s’agit de (property) Person.age ?: number | non défini . Ici le numéro | la partie undefined nous indique qu'il s'agit soit d'un numéro soit d'un numéro non défini car il se peut qu'il ne soit pas présent.

Types de React

React est livré avec un certain nombre de types prédéfinis qui représentent toutes les fonctions, composants, etc. déclarés par React. Pour avoir accès à ces types, nous voudrons ajouter deux packages à notre projet: fil add @ types / react @ types / react-dom .

Supposons que nous avons le JSX: [19659318] <<19459004] div >
< a href = " https://www.google.com " [1945911] 19659011]> Google </ a >
< p href = " https://www.google .com " > Google </ p >
</ div >

C’est un peu difficile à comprendre, mais l’étiquette p a un accessoire href invalide en HTML. C’est là que TS peut nous aider énormément! Dans le code VS, l'ensemble href = "https://www.google.com" est souligné en rouge comme non valide et, lorsque je la survole, je vois:

[ts]  La propriété 'href' ne le permet pas. existe sur le type 'DetailedHTMLProps <HTMLAttributes HTMLParagraphElement>'. [2339]

Si je survole href sur la balise a je verrai (attribut JSX) React.AnchorHTMLAttributes .href ?: string | non défini . Cela signifie que href est un attribut facultatif sur un élément d'ancrage (HTMLAnchorElement). Parce que c'est optionnel ?: il peut s'agir d'une chaîne ou de undefined .

Toutes ces définitions de types proviennent des @ types / Le paquet react qui est un fichier de déclaration de type massive . Pour l'exemple de balise d'ancrage ci-dessus, son interface ressemble à celle ci-dessous, qui déclare un certain nombre de propriétés facultatives spécifiques à ce type de balise:

 interface   AnchorHTMLAttributes  < T > [19659345] s'étend   HTMLAttributes  < T >   {
  télécharger ? :  any ; 
  href ? :  string ; 
  hrefLang ? :  string ; 
  support ? :  string ; 
  rel ? :  string ; 
  cible ? :  chaîne ; 
  type ? :  string ; 
} 

Dites adieu aux propTypes

Les React PropTypes permettent de définir quels prop (et leurs propriétés) types) serait reçu par un composant. Avec TypeScript, elles ne sont plus nécessaires car nous pouvons intégrer cela directement dans notre code TS et résoudre ces problèmes au fur et à mesure que nous tapons le code plutôt que de l'exécuter.

Accessoires des composants fonctionnels

De la valeur par défaut Gatsby nous avons obtenu un composant Header qui ressemble à ceci (j'ai supprimé les styles pour le rendre plus petit):

 import  React  de   "react"  ; 
 import   { Link }   de   "gatsby" ; 

 const   en-tête   =   (). { siteTitle } )   =>   (
   < div > 
     < h1 > 
       < Link   à  =  " / "   =  "[1945911]] [ /  /  /  =    </  Link > 
     </  h1 > 
   </  div >  
) ; 

 export   défaut  En-tête ; 

Nous pouvons voir qu'il reçoit un siteTitle qui semble être une chaîne requise. En utilisant TS, nous pouvons déclarer à l'aide d'une interface quels accessoires sont reçus. Faisons-le également un peu plus sophistiqué en ajoutant une fonctionnalité permettant d’afficher un sous-titre le cas échéant.

 interface   Props   {
  siteTitle :  chaîne
  sous-titre ? :  chaîne
} 

 const   En-tête   =   ( { siteTitle  sous-titre ] : [19459104] Props . ])   =>   (
   < div > 
     < h1 > 
       < Link   à  =  " / "   =  "[1945911]] [ /  /  /  =    </  Link > 
     </  h1 > 
     { sous-titre  &&   < h2 >   { sous-titre ]  [1945932]  h2 >  } 
   </  div >  
) 

Nous avons déclaré une interface Props indiquant que nous recevrons un siteTitle sous forme de chaîne et, éventuellement, un sous-titre qui, une fois défini, sera une chaîne. Dans notre composant, nous pouvons alors savoir le vérifier avec {subTitle &&

{subTitle}

} en se basant sur le fait qu'il ne sera pas toujours là.

Composants de classe

Examinons le même exemple ci-dessus, mais avec un composant basé sur une classe. La principale différence ici est que nous indiquons au composant quels accessoires il recevra à la fin de la déclaration de classe: React.Component .

 interface   Props   {
  siteTitle :  chaîne
  sous-titre ? :  chaîne
} 

 export   default   classe   Header   s'étend à   React .  Composant  < Des objets similaires . ] {
   render  ()   {
     const   { siteTitle  sous-titre }   =   this .  accessoires

     return   (
       < div > 
         < h1 > 
           < Lien vers  =  "/ ">  { siteTitle }  < /  Link > 
         < /  /  h1 > 19659470] { sous-titre  &&   < h2 >  { sous-titre }  < /  /  h2 [1945904] > } 
       < /  div > 
    ) 
  } 
} 

Il nous reste deux choses à faire pour réparer notre installation par défaut de Gatsby. La première est que, si vous regardez le composant Layout vous verrez une erreur sur cette ligne: importez Helmet depuis 'react-helmet' . Heureusement, il est facile à corriger, car react-helmet fournit des déclarations de type en ajoutant le fil add @ types / react-helmet à notre package.

Le dernier problème est de savoir quoi faire de la ligne const Layout = ({children}) => . Quel type d'enfants sera-t-il? Les enfants, si vous n'êtes pas tout à fait sûr, le sont lorsque vous avez un composant React qui reçoit le (s) composant (s) "enfant (s)" à afficher en son sein. Par exemple:

 < div > 
   < p >  Beau paragraphe  < /  p > [19659486] <<19659344] /  div > 

Ici, le composant

est transféré enfant au composant

. OK, revenons à la saisie! Le type d'un enfant dans React est ReactNode que vous pouvez importer du projet react .

 // Import ReactNode 
 import  React .   { ReactNode }   de   à partir de   "réagir" ; 
 // ... autres packages 

 // Définition de l'interface d'accessoires 
 de   ] Accessoires   {
  children :  ReactNode ; 
} 

 // Indiquez à notre composant fonctionnel Layout le typage dont il a besoin (Props) 
 const   Layout   =    { enfants } :  Props )   =>   < div >  { enfants }  < /  div > ; 

 export   default  Mise en page  et 

En prime, vous pouvez maintenant supprimer le code PropTypes fourni par défaut avec Gatsby, car nous procédons maintenant à notre propre vérification de type à l'aide de TypeScript.

Evénements et types

Examinez certains types spécifiques impliqués dans les formulaires, les références et les événements. Le composant ci-dessous déclare un formulaire comportant un événement onSubmit devant alerter le nom saisi dans le champ de saisie, accessible à l'aide du nom nameRef tel qu'il est déclaré en haut du composant. Je vais ajouter des commentaires en ligne pour expliquer ce qui se passe, car c'était un peu bouchée!

 import  Réagissez  sur   "réagissez" ; 

 exportez [19659345] défaut   classe   NomForm   s'étend   Réagissez .  Composant   {
   // Déclare un nouveau Ref qui sera un RefObject de type HTMLInputElement 
  nameRef :  Réagissez .  RéfObjet  < HTMLInputElement >    =  Réagissez . . ] () ; 

   // L'événement onSubmit nous fournit un argument d'événement 
   // L'événement sera un FormEvent de type HTMLFormElement 
  handleSubmit  =   ( événement :  Réagissez .  FormEvent  < HTMLFormElement >  de   ] =>   {
    événement .  preventDefault  () ; 
     // this.nameRef commence à null (jusqu'à ce qu'il soit affecté en tant que référence à l'entrée) 
     // Parce que current commence comme null, le type ressemble à `HTMLInputElement | null` 
     // Nous devons vérifier spécifiquement que this.nameRef a une propriété actuelle 
     if   ( this .  nameRef .  current )   {
       alert  ( cette .  nomRef .  actuel .  valeur )  ; 
    } 
  } ; 

   render  ()   {
     retour   (
       < form   onSubmit  =  { cette .  handleSubmit }  > 
         < input   type  =  " texte "    ref  =  { cette  .  nameRef }    /> 
         < button >  Submit  </  button > 
       </  forme > 
    ) ; 
  } 
} 

Conclusion

Dans cet article, nous avons exploré le monde de TypeScript dans React. Nous avons vu comment trois des principaux frameworks (ou fichiers de démarrage) de create-react-app, Gatsby et Next.js offrent tous un moyen simple d’utiliser TypeScript dans chaque projet. Nous avons ensuite examiné rapidement tsconfig.json et exploré certaines des bases de TypeScript. Enfin, nous avons examiné quelques exemples concrets montrant comment remplacer PropTypes par le système de types de TypeScript et comment gérer un scénario typique avec des références et un événement de formulaire.

Personnellement, j’ai trouvé que TypeScript était facile à utiliser avec les deux, mais en même temps incroyablement frustrant lorsque vous rencontrez une erreur étrange qui n’est pas évident à résoudre. Cela dit, n’abandonnez pas! TypeScript vous assure en outre que votre code est valide et fonctionne comme prévu.

Pour en savoir plus sur la création d'applications avec React:

Consultez notre page All Things React qui contient une excellente collection d’informations et de pointeurs sur l’information React – avec des sujets d'actualité et des informations actualisées allant de la création à la création d'une interface utilisateur convaincante.


Commentaires sont désactivés en mode de prévisualisation.




Source link

février 28, 2019 BFF