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.
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.
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