Fermer

novembre 30, 2020

Rendu au fur et à mesure avec React Suspense


Suspense vous permet de charger des données de manière asynchrone, ou tout autre code de manière asynchrone, et de spécifier de manière déclarative une interface utilisateur de chargement pendant que l'utilisateur attend. Dans cet article, je vais me concentrer sur l'utilisation de Suspense pour la récupération de données avec un exemple utilisant KendoReact Data Grid.

React 16.6 a ajouté un composant qui vous permet de charger de manière asynchrone des composants, des données ou tout autre code, et de manière déclarative spécifier une interface utilisateur de chargement pendant que l'utilisateur attend. Cela nous permet de créer de meilleures applications réactives avec des transitions état / page plus fluides.

Dans cet article, je vais me concentrer sur l'utilisation de Suspense pour la récupération de données avec un exemple utilisant KendoReact Data Grid .

Chargement de données sans suspense

Lorsque vous travaillez avec des données dans React, nous mettons souvent le code pour récupérer les données à côté du composant en l'appelant dans la méthode componentDidMount ou en utilisant le hook useEffect . Regardons un exemple utilisant une grille de données KendoReact qui affiche des informations de base sur l'utilisateur.

Supposons que vous ayez une fonction pour récupérer les données utilisateur:

 export   async   function   getUsers  (  count  =   10 )   {
   const  url  =   `https://randomuser.me/api/?results= [19659018] $ { count }  ` ; 

   const  response  =   wait   fetch  ( url ) ; 
   const  data  =   wait  response .  json  () ; [19659016] return  data .  results .  map  ( ( { name  dob  ,  sexe  lieu } )   =>   ( {
    nom :   ` $ { nom .  premier }   $ { nom .  dernier }  " 
    âge :  ddn .  age 
    sexe :  sexe 
    country :  location .  country 
  } ) ) ; 
} 

et un composant pour l'appeler et affichez le résultat dans un tableau:

 import   { Grid  GridColumn }   from   "@ progress / kendo-react-grid" ; 
 import   { useState  useEffect }   from   "react" ; 
 import  getUsers  de   "./ data / user-service" ; 

 export   default   function   GridContainer  ()   {[19659016] const   [ users  setUsers ]   =   useState  ( null ) ; 

   useEffect  ( ()   =>   {
     const  loadData  =   async   ([19659012])   =>   {
       const  data  =   await   getUsers  () ; 
       setUsers  ] ( data ) ; 
    } ; 
     loadData  () ; 
  }   [] ) ; 

   return   (
     < Grid data  =  { users } > [19659118] < Champ GridColumn  =  "name"   / > 
       < GridColumn field  =  "age"   / [19659117]> 
       < Champ GridColumn  =  "gender"   / > 
       < GridColumn field  =  "country" [19659038] / > 
     < /  Grid > 
  ) ; 
} 

Dans ce composant, j'utilise des crochets pour charger de manière asynchrone les données lorsque ce composant est rendu. [19659004] Lorsque ce composant est rendu, il se comportera comme vous le voyez dans l'enregistrement d'écran ci-dessous.

 Pendant un moment, l'écran indique,

Vous devriez remarquer un délai de quelques secondes entre l'affichage de «Aucun enregistrement disponible» et affichage des données. Il s'agit d'une transition déroutante, surtout si l'utilisateur est sur une connexion Internet lente. Ce problème n'est pas inhabituel. Une façon de résoudre ce problème est d'introduire un état de chargement.

 export   default   function   GridContainer  ()   {
   const   [[ users  setUsers ]   =   useState  ( null ) ; 
   const   [ chargé  setLoaded ]   =   useState  ( false ) ; 

   useEffect  ( ([19659012])   =>   {
     const  loadData  =   async   ()   =>   {
       const  data  =   wait   getUsers  () ; 
       setUsers  ( data ) ; 
       setLoaded  ( true ) ; 
    } ; 
     setTimeout  ( ()   => [19659015] {
       loadData  () ; 
    }   1500 ) ; 
  }   [] ) ; 

   return   (
     <> 
       { chargé ?   (
         < Grid data  =  { users } > 
           < GridColumn field  =  "name"   /  > 
           < Champ GridColumn  =  "age"   / > 
           < GridColumn field  =  "gender"   / > 
           < Champ GridColumn  =  "country"   / > 
         < /  Grid > [19659219])  :   (
         < h2 >  Chargement des données  < /  h2 > 
      )  } 
     < / > 
  ) ; 
} 

Le c La solution que nous venons de faire consistait à ajouter un état chargé à le mettre à jour lorsque les données sont prêtes, et à rendre conditionnellement un état de chargement basé sur l'état chargé . C'est l'un des problèmes que l'équipe React souhaite résoudre avec le mode simultané et le suspense. Au lieu d'écrire du code supplémentaire pour indiquer un état de chargement, vous pouvez signaler à React que quelque chose se charge en arrière-plan et qu'il doit suspendre et afficher une interface utilisateur temporaire jusqu'à ce que la ressource soit prête à être affichée.

] Chargement des données avec React.Suspense

Le motif que vous avez vu dans la section précédente peut être appelé fetch-on-render . Cela signifie que votre code commence à récupérer les données nécessaires pour ce composant uniquement après le rendu du composant. Il y a des moments où cela peut ne pas être une expérience souhaitable, et comme nous savons de quelles données une route ou un composant a besoin, nous pourrions charger les données de manière asynchrone et rendre le composant en parallèle. Nous pouvons nous référer à ce modèle comme render-as-you-fetch et nous pouvons y parvenir en utilisant Suspense.

La façon dont cela fonctionnera est que vous enveloppez votre composant dans et fournissez une solution de secours L'interface utilisateur doit être rendue lorsque ses composants enfants ne sont pas prêts . Dans le composant enfant encapsulé avec Suspense, vous lancerez une promesse qui lit (ou tente de lire) les données pendant que l'extraction est toujours en cours. Lorsque cette promesse est émise, React suspend le rendu du composant et affiche l'interface utilisateur de secours que vous avez spécifiée. Il réessayerait jusqu'à ce que les données soient prêtes, et le composant réel sera rendu.

Nous pouvons ajouter une autre fonction pour récupérer les données en utilisant ce modèle comme suit:

 export   const   fetchUsers   =   ( count  =   10 )   =>   {
   return   wrapPromise  ( getUsers  ( count ) ) ; 
} ; 


 function   wrapPromise  ( promise )   {
   let  statut  =   "en attente" ; 
   let  résultat ; 
   let  suspension  =  promesse  .  puis  (
     ( r )   =>   {
      statut  =   "succès" ; 
      résultat  =  r ; 
    } 
     ( e )   =>   {
      status  =   "erreur" ; 
      result  =  e ; 
    } 
  ) ; 
   return   {
     read  ()   {[19659092] if   ( status  ===   "pending" )   {
         throw  jarretelle ; 
      }   else   if   ( status  ===   "error" )   {
         throw  result ; 
      } [19659009] else   if   ( status  ===   "success" )   {
         return  result ; 
       } 
    } 
  } ; 
} 

La fonction fetchUsers est utilisée pour lancer l'extraction et transmettre la promesse à wrapPromise ]. La fonction wrapPromise renvoie un objet avec une méthode read () qui se comporte de la manière attendue par React Suspense. Si la récupération de données n'est toujours pas résolue, elle jette une promesse. S'il réussit, il renvoie le résultat; sinon, cela génère une erreur.

L'implémentation que vous voyez ci-dessus est similaire à ce que vous trouverez dans la documentation React. Il s'agit d'une version simplifiée de la façon dont ils l'ont implémenté dans le cadre Relay qui servirait d'implémentation de référence pour les auteurs de bibliothèques de données, mais qui ne doit pas être copiée et utilisée en production. Il est fortement déconseillé d'utiliser cette fonctionnalité en production. React Query a une implémentation que vous pouvez vérifier si vous voulez aller plus loin.

Utilisation de React.Suspense

Suspense fait partie d'un ensemble de fonctionnalités que l'équipe React est en train de développer pour aider les applications React à rester réactives et à s'adapter en douceur à la capacités de l'appareil de l'utilisateur et vitesse du réseau. Ils sont encore expérimentaux et sont susceptibles d'être modifiés, mais vous pouvez les essayer dans une version expérimentale. Vous devrez installer cette version pour utiliser les fonctionnalités. Il n'y a aucune garantie de version sémantique pour les versions expérimentales, et les API peuvent être ajoutées, modifiées ou supprimées avec n'importe quelle version expérimentale.

Pour installer la version expérimentale, exécutez:

 npm   install  react @ experimental react-dom @ expérimental

Dans le point d'entrée de votre application, où vous avez quelque chose comme:

 ReactDOM .  render  (
   < React .  StrictMode > 
     < App  / > 
   < /  React .  StrictMode > 
  document .  getElementById  ( "root" ) 
) ; 

Remplacez-le par:

 ReactDOM .  unstable_createRoot  ( document .  getElementById  ( "root" ) ) .  render  (
   <  React .  StrictMode > 
     < App  / > 
   < /  React .  ] StrictMode > 
) ; 

Vous pouvez maintenant envelopper votre composant avec . Vous pouvez insérer le dans et fournir une interface utilisateur de secours.

  < Suspense fallback  =  { < h2 >  Chargement du conteneur  < /  h2 > } > 
   < GridContainer resource  =  { fetchUsers [19659012] () }   / > 
 < /  Suspense > 

Vous avez passé un accessoire ressource à dont la valeur sera le résultat de l'appel de fetchUsers () . Lorsque fetchUsers () est appelé, il commence à récupérer les données et renvoie un objet avec une fonction read () à utiliser pour obtenir les données.

Vous devez maintenant mettre à jour le [19659383] pour lire les données à l'aide de la ressource prop qui lui a été transmise:

 export   default   function   GridContainer  ( { resource  } )   {
   const  users  =  resource .  read  () ; 

   return [19659015] (
     < Grid data  =  { users } > 
       < GridColumn field  =  "nom "  / > 
       < Champ GridColumn  = " age "  / > 
       < Champ GridColumn  = [19659119] "gender"   / > 
       < GridColumn field  =  "country" [19659038] / > 
     < /  Grid > 
  ) ; 
} 

Lorsque ce code est exécuté, il appelle read () pour obtenir les données. S'il n'est pas prêt, il lance une promesse qui le suspend et React restitue le code de secours que vous avez spécifié. Il essaie à nouveau et, si les données sont prêtes, il rend le composant et remplace l'interface utilisateur de secours.

 Au tout début, il affiche

C'est ainsi que vous pouvez utiliser Suspense pour la récupération de données . Ce que je n’ai pas montré, c’est ce qui se passe quand une erreur se produit. Vous gèreriez cela en utilisant la limite d'erreur de React.

C'est un wrap

Suspense est encore une fonctionnalité expérimentale et son API est susceptible de changer. Cela ne fait pas encore partie d'une version stable de React, mais vous pouvez les essayer dans une version expérimentale comme je l'ai montré dans cet article. J'ai décrit comment vous pouvez utiliser ce nouveau mécanisme pour récupérer des données dans React, mais il peut être utilisé pour d'autres cas d'utilisation asynchrones. Vous pouvez trouver un exemple de dépôt pour le code dans cet article sur GitHub .

Références





Source link