React: [Parapluie] Relâcher le suspense

Créé le 13 juil. 2018  ·  83Commentaires  ·  Source: facebook/react

Utilisons ce problème pour suivre les tâches restantes pour publier Suspense en open source.

Version initiale (MVP)

Coeur

  • [x] API pour lire le contexte à partir de n'importe quelle fonction de phase de rendu (@acdlite) [#13139]
  • [x] Masquer le contenu expiré au lieu de le supprimer (@acdlite) [#13120]
  • [ ] Injection automatique de fournisseurs de contexte par racine React (@acdlite) [#13293]
  • [ ] Supprimer le préfixe unstable_ de AsyncMode (peut-être ?)
  • [ ] Prise en charge des thenables synchrones et des promesses qui se résolvent avant la fin de la phase de rendu.

    • [ ] Confirmer qu'un thenable synchrone qui génère une erreur est géré correctement

  • [ ] Confirmez que cela fonctionne avec <div hidden> [#13089]
  • [ ] Pourquoi cliquer sur plusieurs liens de détail dans le projecteur un par un provoque finalement un grand espace réservé même si j'attends chacun d'eux pendant moins que le délai d'espace réservé avant de cliquer sur le suivant ( voir tweet ) ?

Fournisseur de cache simple

  • [ ] Invalidation du cache (@acdlite) [#13337]
  • [ ] Abonnements (@acdlite) [#13337]
  • [ ] Décidez du nom réel

Fractionnement de code

  • [x] Promesse de support en tant que type de composant
  • [x] (peut-être) Open source lazyLoadComponent ?

Tester le moteur de rendu

  • [ ] Finaliser les API publiques pour flushAll , yield , etc.

    • Le plan provisoire est de publier des matchers personnalisés pour chacun des principaux frameworks de test, à la #13236.

Documents

  • [ ] Article de blog
  • [ ] React.Placeholder
  • [ ] fournisseur-cache-simple
  • [ ] Bibliothèque de fractionnement de code sans nom

Suivis

Expiration douce (https://github.com/facebook/react/issues/14248)

  • [ ] Implémenter une API pour les indicateurs de chargement sur place qui ne sont pas des ancêtres
  • [ ] Assurez-vous qu'il existe un moyen d'éviter de faire clignoter le spinner en ligne s'il est assez rapide

Moteur de rendu du serveur de streaming

  • [ ] Implémentez un moteur de rendu de serveur de streaming comme celui de la conférence ZEIT de
  • [ ] Hydratation partielle

Connexes : Parapluie de découpage du temps (https://github.com/facebook/react/issues/13306)

React Core Team Umbrella

Commentaire le plus utile

@mschipperheyn

Il s'agit d'un projet pluriannuel. La réponse honnête est que cela a engendré bien plus de travail que nous ne le pensions lorsque nous avons commencé il y a deux ans.

Mais la bonne nouvelle est que parce que nous l'utilisons maintenant massivement en production, les pièces manquantes sont claires et nous voyons le bout du tunnel. Ce n'est pas théorique - il y a un ensemble fini de choses que nous devons terminer avant de pouvoir confortablement dire qu'il est prêt pour une large adoption.

Voici un état approximatif des différents flux de travail aujourd'hui :

  • <Suspense> API pour le fractionnement de code avec lazy . ( livré dans React 16.6)

    • Comme vous le savez peut-être, vous pouvez déjà utiliser celui-ci.

  • API en mode simultané, par exemple createRoot et useTransition . ( disponible dans les experimental )

    • Solution de compatibilité pour les bibliothèques de type Flux. ( en cours @bvaughn , https://github.com/reactjs/rfcs/pull/147)

    • Changer le modèle prioritaire pour un modèle plus sensé. ( en cours @acdlite , https://github.com/facebook/react/pull/18612)

    • Ne permettez que la dernière transition en attente de se terminer. ( en cours @acdlite)

    • API hors écran ( en cours @lunaruan)

    • Effets de feu lors du masquage/affichage du contenu pour Suspense

    • Effets de feu lors du masquage/affichage du contenu pour Offscreen

    • Afficher et masquer les enfants du portail si nécessaire

    • S'aligner sur les travaux de normalisation en cours pour la planification ( pas commencé )

    • Correction de bugs majeurs connus ( en cours @gaearon et @acdlite)

    • Changer la sémantique des événements. ( en cours @sebmarkbage @trueadm)

    • Déléguer aux racines au lieu du document pour permettre une adoption plus progressive ( en cours , @trueadm)

    • Videz les événements discrets en phase de capture.

    • Envisagez d'obtenir la priorité par défaut de event pour mieux jouer avec le code impératif.

    • Finalisez les autres sémantiques et valeurs par défaut de l'API. ( pas commencé )

    • Mettre à jour les saisies et la documentation.

  • Suspense pour la récupération de données

    • Prise en charge de bas niveau pour signaler qu'un composant n'est pas prêt à être rendu (techniquement disponible dans React stable également, mais cette API n'est pas considérée comme stable).

    • Le moteur de rendu du serveur vide immédiatement les solutions de secours Suspense ( disponibles dans les versions expérimentales)

    • Une solution pour les cas d'utilisation de GraphQL (Relay Hooks, livrés ).

    • Une solution pour les cas d'utilisation non-GraphQL ( en cours @sebmarkbage en collaboration avec Next.js).

    • Une intégration de bundle pour les dépendances basées sur les données. ( en cours )

    • Finalize Blocks API, y compris le contexte.

    • Une solution de mise en cache générique. ( pas commencé )

    • Une sorte d'intégration de routeur.

J'ai presque l'impression que "c'est en production sur Facebook, alors c'est fini".

Je peux voir à quoi cela pourrait ressembler, bien que cette lecture soit un peu démoralisante. :-) Nous avons travaillé sans arrêt dessus pendant tous les mois passés, et de nombreux aspects techniques sont soit terminés, soit sur le point de l'être. La plupart des travaux restants se répartissent en deux catégories :

  • Corriger les défauts que nous avons découverts dans les conceptions initiales avant de les cimenter dans une version stable. Si nous devions sortir ce que nous avons maintenant, nous devrions procéder à des changements importants dans quelques mois. Ce ne serait que déroutant.

  • Compatibilité de l'écosystème et bonnes valeurs par défaut. Cela n'aide pas si nous publions quelque chose que personne ne peut utiliser aujourd'hui parce que cela ne fonctionne pas avec leurs bibliothèques ou leurs approches existantes. Ainsi, le gros du travail (par exemple, la compatibilité avec les bibliothèques de type Flux via useMutableSource , la sélection d'une meilleure sémantique des événements, l'envoi d'une stratégie de mise en cache recommandée) consiste à s'assurer que vous serez réellement en mesure d' utiliser ce que nous avons publié. C'est une longue queue.

En termes de "pouvez-vous utiliser aujourd'hui"... Techniquement, vous pouvez utiliser tout cela aujourd'hui. Nous faisons. Plus précisément, nous utilisons les crochets de relais et le mode simultané. Nous avons encore d'importants changements prévus et des problèmes connus, donc l'état actuel n'atteint pas la barre où nous le considérerions prêt pour une large adoption. Bien sûr, si cela ne vous @experimental comme nous le faisons.

Je ne dirais pas que Facebook est dans une position particulière ici en termes de « finis ». Bien au contraire, nous n'avons pas fini – mais en interne, nous sommes prêts à tolérer le roulement et à construire sur un train en mouvement parce que c'est ainsi que nous savons que ce que nous construisons est solide. Sans ce dogfooding lourd, les défauts que nous avons découverts en six mois prendraient plusieurs années à découvrir et à reconcevoir.

Pour résumer : il y a plus de travail à faire.

Tous les 83 commentaires

Exposer unstable_AsyncMode (peut-être ?)

N'est-ce pas déjà exposé ?

Je voulais dire supprimer le unstable_

J'attends avec impatience l' open source de la bibliothèque de fractionnement de code sans nom 💯

Qu'est-ce que cela signifie [Parapluie] ?🤔☂️

Cela signifie que c'est une fonctionnalité qui impacte plusieurs projets/packages/outils.

@ghoullier je vois, merci beaucoup !

Salut @acdlite , juste une question sur la meilleure façon de s'y préparer. Ne pas demander / s'attendre à n'importe quel type de calendrier, mais se demander :

Vous attendez-vous actuellement à ce que ces fonctionnalités soient intégrées à React 16 et faciles à adopter progressivement, comme la nouvelle API de contexte qui a atterri avec 16.3 ?

Ou pensez-vous que ce sera quelque chose qui poussera React vers la v17 et nécessitera plus de travail pour être adopté ?

Demander parce que je travaille sur une feuille de route qui recoupe de manière significative à peu près tout sur votre liste et j'essaie de trouver la meilleure façon de gérer cela.

Avez-vous également des conseils sur la meilleure façon de préparer (en termes de code écrit aujourd'hui, qui se veut futur compatible avec ces améliorations de React) - polyfills / techniques / etc?

(excuses si ces questions trouvent une réponse ailleurs et que je les ai manquées)

Ajout d'une autre question aux questions de @JedWatson :

  • Nous n'avons pas non plus besoin/nous attendons à obtenir un calendrier pour une version stable, mais serait-il possible/utile d'obtenir une nouvelle préversion ? (AFAIK, la dernière version est 16.4.0-alpha.0911da3 partir de février.)

Merci! ️

OMI, ils fourniront un article de blog comme avant avant qu'il ne soit débarqué.

Et je pense que vous n'avez pas besoin de trop vous préparer car il n'y a pas de changement radical (il a de nombreuses fonctionnalités qui semblent peut-être différentes / en conflit avec les pratiques actuelles, comme le redux fetch avec suspense, mais il y aura un codemod ou une encapsulation facile pour ce faire, vous savez, fb a des composants 3W+). Et si vous regardez le discours de @acdlite (à propos du suspense ssr dans ZEIT) et de @gaearon (à propos du suspense client en Islande), vous saurez que vous n'avez pas à vous en soucier trop et que ce n'est pas invasif.

Au fait, vous pouvez simplement rechercher la clé 'Umbrella' dans le repo et vous trouverez plus d'informations comme #8830 et #12152

AFAIK, la dernière version est la 16.4.0-alpha.0911da3 de février.

IIRC, c'est une mauvaise opération ?

Je travaille sur le déploiement du module suspense et de nouvelles API sur Facebook. Au cas où @acdlite serait occupé par autre chose, j'aimerais partager certaines de mes réflexions sur notre expérience sur Facebook et répondre à quelques questions de @JedWatson.

Vous attendez-vous actuellement à ce que ces fonctionnalités soient intégrées à React 16 et faciles à adopter progressivement, comme la nouvelle API de contexte qui a atterri avec 16.3 ?

Je ne sais pas s'il viendra avec React 16 ou 17. Selon l'équipe React, il devrait sortir avant la fin de cette année, ce qui dépend de la façon dont il fonctionne sur Facebook et de la façon dont l'API associée est prête ou ne pas. Mais au niveau du code, je suis heureux de dire que ce serait facile à adopter, car nous expérimentons depuis pas mal de temps sur facebook. La fonction de suspension fonctionnera toujours pour la base de code existante. Mais avec des changements supplémentaires (comme le rendu asynchrone), vous aurez plus de bonus que la nouvelle fonctionnalité vous apportera.

Avez-vous des conseils sur la meilleure façon de préparer (en termes de code écrit aujourd'hui, qui se veut futur compatible avec ces améliorations de React) - polyfills / techniques / etc?

Je dirais que la migration est plutôt incrémentale et progressive. Comme @NE-SmallTown l'a dit, nous ne voulons pas introduire de changements de rupture. Ce serait également pénible à déployer sur Facebook car nous avons une base de code tellement importante. Mais jusqu'à présent, le déploiement s'est déroulé sans heurts et ne nécessite pas de modifications supplémentaires.

@JedWatson

Vous attendez-vous actuellement à ce que ces fonctionnalités soient intégrées à React 16 et faciles à adopter progressivement, comme la nouvelle API de contexte qui a atterri avec 16.3 ?

Progressivement. Toujours progressivement :) Sinon, nous ne serions pas en mesure d'expédier cela sur Facebook.

Voici ce que j'attends :

| | Cliente | Rendu côté serveur |
|-----------------|----------------------------|-- --------------------------------------------|
| Suspense | Fonctionne partout* | Mêmes contraintes que le moteur de rendu du serveur existant |
| Rendu asynchrone | S'inscrire en utilisant <AsyncMode> | Mêmes contraintes que le moteur de rendu du serveur existant |

*En mode de synchronisation, delayMs est toujours 0 . Les espaces réservés s'affichent immédiatement.

Suspense fonctionnera sans aucune modification de vos composants existants. À un moment donné, nous avons pensé que nous pourrions avoir besoin d' <StrictMode> compatibilité

L'idée est donc que les utilisateurs commenceront à migrer vers Suspense avant même d'être prêts à migrer vers le rendu asynchrone. Ensuite, une fois qu'un sous-arbre est prêt, ils peuvent s'inscrire en encapsulant <AsyncMode> .

Pour les nouvelles applications, cependant, l'histoire est différente : devenez asynchrone par défaut. Nous allons introduire une nouvelle API racine (un remplacement pour ReactDOM.render ) qui est asynchrone uniquement.

Il y aura une période délicate après la version initiale où de nombreux frameworks tiers (Redux, Apollo, React Router...) peuvent ne pas fonctionner correctement en mode asynchrone. Cela pourrait nuire à l'adoption pendant un certain temps. Mais l'idée est que les nouvelles fonctionnalités seront si convaincantes qu'il ne faudra pas longtemps aux bibliothèques pour s'adapter ou être remplacées par une alternative compatible asynchrone.

Avez-vous également des conseils sur la meilleure façon de préparer (en termes de code écrit aujourd'hui, qui se veut futur compatible avec ces améliorations de React) - polyfills / techniques / etc?

Enveloppez le tout dans <StrictMode> et assurez-vous qu'il n'y a pas d'avertissements. Nous aurons des guides de migration plus détaillés à mesure que nous nous rapprochons de la sortie.

Il y aura une période délicate après la version initiale où de nombreux frameworks tiers (Redux, Apollo, React Router...) peuvent ne pas fonctionner correctement en mode asynchrone.

Apollo ne fait pas mal - nous serons prêts ! ??

Sérieusement, nous :heart: all things React, donc s'assurer que nous sommes en ligne avec ces changements pour la version initiale n'est pas seulement une priorité élevée, mais c'est aussi quelque chose qui nous enthousiasme ! Merci pour tout votre travail incroyable sur ce @acdlite !

Je vais intervenir et dire que l'équipe Redux travaille sur une compatibilité asynchrone pour React-Redux.

J'ai présenté une feuille de route potentielle sur https://github.com/reduxjs/react-redux/issues/950 . TL ; DR :

  • Nous espérons que React-Redux 5.1 fonctionnera avec <StrictMode> sans avertissement (PR actuel : https://github.com/reduxjs/react-redux/pull/980 )
  • 6.0 sera une réécriture interne pour utiliser la nouvelle API de contexte, ajouter un transfert de référence et éventuellement d'autres modifications, mais essayez de conserver autant que possible l'API publique actuelle (c'est-à-dire <Provider> et connect() ). Nous verrons à quel point cela fonctionne avec le rendu asynchrone et trouverons la meilleure voie à suivre. (Mon précédent PR de preuve de concept se trouve sur https://github.com/reactjs/react-redux/pull/898 , mais nous le referons probablement sur la base d'autres leçons tirées du travail 5.1.) Il est probable que cette version nécessiterait au minimum React 16.5, en raison du besoin d'un nouveau contexte et probablement aussi du PR "lire le contexte à partir des méthodes de cycle de vie" encore non publié qui vient d'être fusionné.
  • Après cela, nous sommes ouverts aux idées pour une autre API React-Redux (oui, oui, cela inclut peut-être des accessoires de rendu, des personnes).

Nous apprécierions d'avoir plus de regards sur notre WIP, et j'espère que les gens pourront nous donner plus de commentaires et de discussions sur la façon dont ils envisagent d'utiliser Redux avec React Suspense et le rendu asynchrone afin que nous puissions nous assurer que les cas d'utilisation sont correctement couverts. Nous espérons également avoir d'autres discussions avec l'équipe React sur les contraintes exactes avec lesquelles nous devons travailler, et ce serait utile si nous pouvions obtenir des exemples d'applications qui nous permettraient de voir quels problèmes nous devons résoudre pour tous cela fonctionne correctement.

dans l'attente de la sortie du rendu Async et du Suspense

@acdlite Question également sur le suspense et le rendu asynchrone.
Ma question est une fois qu'elles sont introduites et que l'on commence à écrire des applications avec cette nouvelle version de React : cela signifie-t-il que l'API React et la façon dont les gens codent en réagissent changeront également ? (même s'ils ne prévoient pas d'utiliser les fonctionnalités de suspense et de rendu asynchrone ?)

Je suppose qu'il peut être plus difficile d'écrire du code de réaction avec suspense et rendu asynchrone (peut-être en raison d'une nouvelle API ou d'autres contraintes), et pour ceux qui n'en ont pas besoin, pourquoi les forcer à utiliser React d'une nouvelle manière ? Et ne pas leur permettre de coder en réaction comme ils le font maintenant ?

Je suppose qu'il peut être plus difficile d'écrire du code de réaction avec du suspense

Avez-vous eu la chance de regarder la seconde moitié de mon discours? Je dirais plutôt le contraire - il est beaucoup moins compliqué d'utiliser le suspense pour la récupération de données qu'autre chose (y compris Redux, l'état local ou une autre bibliothèque).

@gaearon je n'ai pas. Je parlais plus en théorie. Imaginez qu'il y ait déjà un ensemble de personnes qui savent réagir. Si les gens n'ont pas besoin de la fonctionnalité de rendu asynchrone et de suspense, pourquoi les forcer à apprendre de "nouvelles" réactions ? Surtout si la "nouvelle" réaction est plus rusée à utiliser ? Mais : je ne suis pas bien informé, donc je peux me tromper en disant à propos de la partie "la plus délicate" - je partage juste certaines de mes réflexions :).

D'une certaine manière, je dis que si 10 % des applications ont besoin de la fonctionnalité Suspense et du rendu asynchrone, pourquoi dans ces 90 % des autres cas, forcer les gens à apprendre de « nouvelles » réactions ? Mais encore une fois, je me trompe peut-être, car je n'ai pas encore recueilli beaucoup d'informations sur la suspension et le rendu asynchrone.

Je pense qu'il est difficile d'avoir une conversation si vous n'avez pas encore regardé mes démos .

Pour être clair : il n'y a pas de "nouveau React", ces fonctionnalités ne cassent aucun schéma existant 🙂. Ils sont additifs. Vous n'avez pas non plus besoin d'écrire du code d'une manière complètement différente pour utiliser ces fonctionnalités, bien que certaines d'entre elles ne fonctionnent que si vous utilisez des méthodes de cycle de vie modernes .

Bien que cela ne soit pas directement lié à votre préoccupation, je ne suis pas d'accord qu'ils soient "plus difficiles à utiliser". Je pense que le suspense est beaucoup plus simple à utiliser que tout autre mécanisme de chargement existant actuellement. C'est la raison pour laquelle je suis si excité à ce sujet. Mais encore une fois, vous n'êtes pas obligé d'utiliser les nouvelles fonctionnalités si vous ne le souhaitez pas. Les anciens modèles continueront de fonctionner.

Je recommande vraiment de regarder mon discours . Je suis sûr que cela aura beaucoup plus de sens une fois que vous verrez ces fonctionnalités en action.

@gaearon

Tous les anciens modèles continuent de fonctionner.

Merci pour vos commentaires Dan. Oui, c'est ce que je pensais, je suppose que si les gens n'ont pas besoin de ces fonctionnalités, ils devraient pouvoir écrire comme ils le faisaient avant que ces fonctionnalités ne soient ajoutées.

Bonne chance.

Hey Dan (@gaearon), je ne pinaille pas mais je veux le comprendre. Au dessus tu as dit :

Mais encore une fois, vous n'êtes pas obligé d'utiliser les nouvelles fonctionnalités si vous ne le souhaitez pas. Les anciens modèles continueront de fonctionner.

Ce qui suggérerait que je puisse coder dans le nouveau React de la même manière que dans "l'ancien" React, par exemple, je pourrais utiliser les méthodes du cycle de vie de la même manière, etc. n'est-ce pas ?

Cependant, ici , bvaughn dit que getDerivedStateFromProps (ou componentWillReceiveProps) pourrait être appelé plusieurs fois pour une mise à jour, d'où sa solution pour ne pas récupérer les données à l'intérieur.

Ma question est donc, après tout, il semble que nous ne puissions pas utiliser le nouveau React exactement de la même manière qu'avant, n'est-ce pas ? Parce que AFAIK dans le composant de réaction actuelWillReceiveProps n'est pas appelé plusieurs fois pour une mise à jour, n'est-ce pas ?

@giorgi-m : oui, les méthodes de cycle de vie changent, mais le fait est que Suspense lui-même est une fonctionnalité opt-in. Toutes vos méthodes de rendu React existantes et le comportement de rendu de React fonctionneront tels quels. Cependant, _si_ vous acceptez en ajoutant une balise <AsyncMode> à une partie de votre application, _et_ vous commencez à utiliser l'approche de Suspense pour indiquer les besoins en données asynchrones, _alors_ vous pouvez en profiter. Rien de tout cela ne se produit si vous ne l'ajoutez pas à votre base de code.

@giorgi-m componentDidUpdate doit être utilisé au lieu de componentWillReceiveProps ou getDerivedStateFromProps .

@markerikson Donc vous dites que ce que bvaughn a dit ici , que _getDerivedStateFromProps_ peut être appelé plusieurs fois pour une mise à jour, n'est pas nécessairement le cas, si je n'ai pas activé le <AsyncMode/> ?
(désolé d'avoir posé de telles questions, elles m'apparaissent de temps en temps et n'ont pas trouvé de ressource qui couvrirait tout).

ps. bvaughn n'a pas non plus mentionné l'optionnalité de cela dans le fil lié, ce qui a éveillé mes soupçons.

Une méthode de mise en file d'attente des mises à jour asynchrones (par exemple deferSetState() pour les composants de classe par opposition aux unstable_deferredUpdates() spécifiques au moteur de rendu) devrait-elle être ajoutée à la liste de contrôle principale ?

D'après ce que j'ai compris, toutes les mises à jour des fibres en async mode seront asynchrones, ce qui signifie en théorie que deferSetState() serait inutile. Cependant, la démo unstable-async/suspense mélange une mise à jour synchrone et une mise à jour asynchrone et je ne sais pas comment cela peut être accompli en mode async (pour les composants "universels").

C'est dans la liste de contrôle du parapluie coupe-temps.

Promesse de support en tant que type de composant

En lien avec cela, lorsque vous avez :

const PromiseType = new Promise(() => {})
class A extends Component {
    componentDidMount() {}
    componentDidUpdate() {}
    render() {
        return <div><PromiseType></PromiseType></div>
    }
}

Existe-t-il des heuristiques quant au moment où les cycles componentDidUpdate vie componentDidMount et componentDidUpdate seraient appelés.

  1. Lorsque tous les enfants ont été résolus (y compris la promesse), ce qui dans ce cas signifie qu'ils ne seront pas appelés étant donné que la promesse n'est jamais résolue ?
  2. Quand tous les enfants hôtes immédiats ont été rendus ?

@thysultan : componentDidMount et componentDidUpdate sont appelés dans la phase de validation, lorsqu'un arbre d'interface utilisateur a été entièrement rendu et appliqué au DOM.

Donc, sur la base de ma compréhension de Suspense, je pense que la réponse est que l'instance A ne serait jamais réellement montée. Si PromiseType _did_ était résolu, mais que l'un de ses descendants ultérieurs tentait également d'attendre une promesse qui ne se résoudrait jamais, il ne serait plus jamais monté. Ainsi, cDM et cDU ne seraient jamais exécutés dans ces exemples.

(Quelqu'un n'hésite pas à me corriger si mes hypothèses sont fausses ici :) )

Oui, componentDidMount ou componentDidUpdate ne s'exécutent que dans la phase de validation qui ne s'exécute qu'une fois que tout l'arbre a été résolu. Cet arbre peut inclure des espaces réservés que vous avez explicitement placés là (selon que quelque chose à l'intérieur est toujours suspendu après que nous ayons attendu assez longtemps) - mais si vous rendez explicitement un enfant sans espace réservé autour de lui, vous ne pouvez jamais vous retrouver dans une situation où il n'est "pas prêt".

J'ai vraiment hâte de pouvoir jouer avec cela (même parcouru beaucoup de code source pour découvrir que vous n'aviez pas encore mis de version fonctionnelle de cela sur le World Wide Web).

Y a-t-il quelque chose que nous puissions faire pour aider à obtenir cette publication ? :RÉ

Vous pouvez compiler à partir du master si vous voulez jouer. Voir les instructions dans fixtures/unstable-async/suspense

@gaearon Ai-je raison de dire qu'il s'agit uniquement de son état actuel côté client (donc plus de travail à faire pour prendre en charge le rendu côté serveur) ?

EDIT, trouvé la réponse : pour tous ceux qui souhaitent utiliser Suspense dans SSR pour des applications universelles. J'ai trouvé ce commentaire de Dan qui nous fait savoir qu'il s'agit du côté client uniquement pour l'instant. Cependant, ce commentaire pointe également vers https://www.youtube.com/watch?v=z-6JC0_cOns qui parle des implications possibles pour la RSS.

En fait, nous commençons bientôt quelques travaux liés au cas SSR.

Imaginez ce scénario dans une application React asynchrone s'exécutant sur un appareil mobile bas de gamme :

  1. Il y a un chargement d'annonce externe, utilisant tout le processeur (😓)
  2. L'utilisateur clique sur un lien et le routeur déclenche un nouveau rendu
  3. React est en mode asynchrone, il attend donc que Chrome/Safari lui donne l'autorisation d'utiliser le processeur, mais l'annonce continue de se charger pendant 3 secondes de plus
  4. L'utilisateur pense que l'application ne fonctionne pas

Ce problème pourrait être évité en utilisant la même technique <Placeholder> discutée pour Suspense, en affichant un spinner après 1 seconde par exemple.

Ce scénario a-t-il été envisagé ? <Placeholder> fonctionnera-t-il pour les rendus asynchrones lents ?

@luisherranz Il existe deux mécanismes pour empêcher cela :

  1. React a une date limite associée à chaque mise à jour. Les mises à jour à partir de clics et d'autres interactions comme celle-ci devraient s'afficher dans un délai d'environ 150 ms, sauf si vous optez explicitement pour un délai plus long (par exemple, pour les mises à jour non essentielles). Ainsi, React forcera le flush de manière synchrone si quelque chose monopolise le thread.

  2. React n'utilise plus requestIdleCallback car en effet les navigateurs ne sont pas assez agressifs pour le programmer. L'approche de planification exacte peut également changer au fil du temps, mais c'est certainement quelque chose qui nous tient à cœur.

Merci beaucoup pour la réponse rapide Dan.

  1. React a une date limite associée à chaque mise à jour

Impressionnant. Existe-t-il déjà une API en place que nous pourrions tester ?

  1. React n'utilise plus réellement requestIdleCallback car en effet les navigateurs ne sont pas assez agressifs pour le programmer.

C'est aussi ce que nous avons expérimenté. Parfois, dans une application encombrée avec des publicités externes et des intégrations de Twitter ou de YouTube, cela peut prendre plusieurs secondes jusqu'à ce que le requestIdleCallback soit appelé et que le rendu soit terminé. Alors à ça.

BTW, pour nous, il existe un autre cas d'utilisation lié à votre première réponse : nous essayons d'utiliser des lazyloads avec deux décalages. Le premier déclenche un rendu asynchrone, le second déclenche un rendu synchro si l'async n'est pas terminé. Quelque chose comme ça:

  1. L'utilisateur fait défiler vers le bas et c'est à 1200px d'un élément lourd : par exemple le prochain article d'un blog.
  2. Le premier offet déclenche un rendu asynchrone du post suivant.
  3. L'utilisateur continue de faire défiler vers le bas et c'est à 600px du prochain message.
  4. Le deuxième décalage se déclenche : si la publication asynchrone est terminée (componentDidMount appelé), rien ne se passe, mais si ce n'est pas le cas, il déclenche un rendu synchronisé de l'ensemble de la publication.

Donc, au lieu du temps, nous aimerions contrôler la chasse d'eau avec un deuxième déclencheur. Est-ce que ça fait du sens? Serait-ce possible?

Existe-t-il déjà une API en place que nous pourrions tester ?

Je ne sais pas si vous voulez dire sur maître ou non (le mode async n'est pas officiellement disponible dans les versions npm), mais le délai d'expiration est attribué automatiquement à chaque mise à jour. Pour les événements comme les clics, c'est ~ 150 ms en mode prod. Vous ne pouvez pas le définir, bien que vous puissiez opter pour une mise à jour différée (plus longue) si vous le souhaitez avec une API instable spéciale.

Donc, au lieu du temps, nous aimerions contrôler la chasse d'eau avec un deuxième déclencheur. Est-ce que ça fait du sens? Serait-ce possible?

Ouais c'est possible. J'ai décrit un mécanisme comme celui-ci ici : https://github.com/oliviertassinari/react-swipeable-views/issues/453#issuecomment -417939459.

Je ne sais pas si vous voulez dire sur maître ou non (le mode async n'est pas officiellement disponible dans les versions npm)

Oui, nous utilisons le package npm avec <unstable_AsyncMode> , flushSync et unstable_deferredUpdates .

S'il vous plaît, commencez à publier des versions alpha/bêta avec ces modifications apportées à npm ! ??

Ouais c'est possible. J'ai décrit un mécanisme comme celui-ci ici : oliviertassinari/react-swipeable-views#453 (commentaire).

Brillant. Bien mieux que notre implémentation actuelle utilisant unstable_deferredUpdates :)

J'ai hâte de commencer à utiliser <div hidden> . Vous faites un travail incroyable.

@luisherranz Attention, ces choses _sont_ instables. Peut avoir des bogues ou être assez inefficace (par exemple, une optimisation cruciale — "reprendre" — n'est pas encore implémentée). Nous supprimons également unstable_deferredUpdates en faveur du nouveau module schedule ( schedule.unstable_scheduleWork ).

Oui, nous ne l'utilisons que pour une petite partie de l'application et nous testons intensivement mais jusqu'à présent tout va bien :)

PEUT ÊTRE HORS SUJET :
requestIdleCallback n'est appelé que 20 fois par seconde - Chrome sur ma machine Linux 6x2, ce n'est pas vraiment utile pour le travail d'interface utilisateur.
requestAnimationFrame est appelé plus souvent, mais spécifique à la tâche que le nom suggère.

Nous avons cessé d'utiliser requestIdleCallback pour cette raison.

Qu'utilisez-vous à la place de requestIdleCallback ?

Ah, bien sûr. Que je suis bête. Je me demandais quelle API de navigateur le module de planification utilise sous le capot au lieu de requestIdleCallback . J'aurais dû poser la question plus clairement. ??

Salut,

tout en essayant de comprendre Suspense, j'ai reconnu que je n'avais aucune idée de quelle partie d'une application est réellement "suspendue" lorsque j'utilise le composant Suspend 😳😱.

Dans l'exemple suivant, je m'attendrais Title ce que Spinner après 1000ms et UserData après ~2000ms (car le "chargement" des données pour ce composant prend 2000ms).
Mais ce que je vois, c'est que Title apparaît pour la première fois avec Spinner après 1000ms.

// longRunningOperation returns a promise that resolves after 2000ms
const UserResource = createResource(longRunningOperation);

function UserData() {
  const userData = UserResource.read(cache, "Lorem Ipsum");
  return <p>User Data: {userData}</p>;
}

function Spinner() {
  return <h1>Fallback Loading Spinner</h1>;
}

function Title() {
  return <h1>Hello World</h1>;
}

function App() {
  return (
    <React.Fragment>
      <Title />
      <Suspense maxDuration={1000} fallback={<Spinner />}>
        <UserData />
      </Suspense>
    </React.Fragment>
  );
}

unstable_createRoot(document.getElementById("mount")).render(<App />);

(Vous pouvez trouver l'exemple complet qui utilise React 16.6.0-alpha.8af6728 ici sur codesandbox )

Existe-t-il un moyen de rendre Title immédiatement visible et de "suspendre" uniquement l'autre partie de l'application ? Ou ai-je mal compris peut-être complètement Suspense ? (S'il y a une meilleure façon de poser ce genre de questions, faites-le moi savoir)

Merci!

Salut @nilshartmann ! Excellente question !

Existe-t-il un moyen de rendre le titre immédiatement visible et de "suspendre" uniquement l'autre partie de l'application ?

Si je comprends bien, vous devrez explicitement dire à React de _pas attendre_ avant de vider Title dans le DOM comme dans cet exemple afin de rendre Title immédiatement visible et de "suspendre" uniquement l'autre partie de l'application en enveloppant les parties que vous vous attendriez à être immédiatement rendues dans un <Suspense maxDuration={0}> .

J'imagine que c'est le cas à cause de certains mécanismes sous-jacents de planificateur de niveau inférieur ? J'aimerais aussi mieux comprendre cela, mais cela devrait résoudre votre problème pour le moment.

Je suis ravi d'entendre ce qui se passe réellement là-bas.

(S'il y a une meilleure façon de poser ce genre de questions, faites-le moi savoir)

Je ne suis pas sûr qu'il y ait. Cela me semble assez clair. Merci d'avoir posé la question!

@TejasQ Dans mon navigateur, le chargement de votre exemple

@TejasQ merci pour votre réponse, mais @karlhorky a raison : maintenant le spinner apparaît immédiatement.

Aïe ! J'ai manqué ça. J'ai essayé. Permettez-moi d'y jeter un autre coup d'œil et de revenir vers vous. J'ai dû rater quelque chose. ️

~Mise à jour : j'essaie de comprendre ici et nous pouvons collaborer si quelqu'un est intéressé à le faire ensemble en temps réel.~

Deuxième mise à jour : @philipp-spiess et moi l'avons regardé et je suis vraiment perplexe. Je ne le comprends toujours pas. À ce stade, je ne sais pas s'il s'agit d'un bogue car il s'agit en fait d'une fonctionnalité unstable_ et alpha, ou si c'est quelque chose que je ne vois tout simplement pas.

Dans les deux cas, j'ai l'impression que l'équipe principale aura des réponses utiles ou pourra utiliser votre question pour rendre React encore meilleur/plus accessible.

Voyons ce qu'ils ont à dire. 😄 Merci de l'avoir signalé, @nilshartmann !

Cela a-t-il été publié dans le cadre de React v16.6 ? L' article de blog montre un exemple de code utilisant Suspense :

import React, {lazy, Suspense} from 'react';
const OtherComponent = lazy(() => import('./OtherComponent'));

function MyComponent() (
  <Suspense fallback={<div>Loading...</div>}>
    <OtherComponent />
  </Suspense>
);

Cela a-t-il été publié dans le cadre de React v16.6 ?

Seul le cas d'utilisation du chargement paresseux, et uniquement en mode synchronisation. Le mode simultané est toujours WIP.

@nilshartmann

Dans l'exemple suivant, je m'attendrais à ce que le titre soit visible immédiatement, Spinner après 1000 ms et UserData après ~ 2000 ms (car le "chargement" des données de ce composant prend 2000 ms).

Je pense que vous êtes un peu confus au sujet de ce que fait maxDuration . C'est un nouveau modèle mental mais nous n'avons pas encore eu le temps de le documenter. Cela restera donc confus pendant un certain temps jusqu'à ce que le mode concurrent soit dans une version stable.

Félicitations pour l'annonce de la proposition de crochets. J'aimerais partager quelque chose avec l'équipe. Il y a quelque temps, j'ai publié un composant appelé React Async , qui présente des fonctionnalités similaires à Suspense. Essentiellement, il gère la résolution Promise et fournit des métadonnées telles que isLoading, startAt et des méthodes telles que reload et cancel, le tout avec une API déclarative (et un hook useAsync est en route).

Maintenant, ma principale préoccupation est de savoir comment cela va s'intégrer à Suspense. Pour la plupart, je peux probablement utiliser les API Suspense de React Async et fournir aux utilisateurs l'API React Async familière et simple, tout en offrant gratuitement les fonctionnalités de planification de Suspense. Pour ce que j'ai vu, je pense sincèrement que l'API React Async est plus sensée et accessible que les API Suspense plus abstraites. Essentiellement, React Async essaie d'offrir une API plus concrète qui fonctionne pour un sous-ensemble légèrement plus petit de cas d'utilisation.

J'ai été surpris d'apprendre l'existence de la bibliothèque React Cache. Pour React Async, je n'ai délibérément pas inclus de mécanisme de cache, mais j'ai choisi de traiter les promesses vanille. L'ajout de la mise en cache en plus est assez facile.

Enfin, je suis préoccupé par l'accès aux fonctionnalités Suspense à partir de crochets personnalisés. Le suspense semble s'appuyer fortement sur plusieurs composants intégrés, ce qui rend impossible (je pense?) De les utiliser à partir d'un crochet. Y aura-t-il des crochets à suspense ? Ou existe-t-il un autre moyen d'intégrer les deux ?

Bonjour. Comment puis-je tester le code avec Suspense/Lazy ?
maintenant renderer.create(...)toTree() lance
"toTree() ne sait pas encore comment gérer les nœuds avec tag=13"

Pourquoi les accessoires maxDuration dans Suspense ne sont utilisés que dans le Concurrent Mode plutôt que dans les modes synchro et concurrent. Quelqu'un peut-il aider à expliquer?

(Pour le moment), cela signifie combien de temps Concurrent Mode est autorisé à laisser cet arbre en attente avant de le forcer à s'engager - il contrôle efficacement la date limite de découpage du temps, et le découpage du temps n'existe pas en mode Sync. Attendre avant de valider l'arborescence ferait nécessairement le commit... pas Sync.

J'ai utilisé Suspense dans une application interne pour la récupération de données et j'ai très rapidement découvert la raison pour laquelle il n'est pas encore destiné à être utilisé pour la récupération de données.

Finalement, cependant, il est destiné à être utilisé pour récupérer des données. Étant donné qu'il semble peu probable que l'API change de manière significative, à l'exception peut-être du fournisseur de cache, comment Suspense est-il censé fonctionner si vous devez modifier les données après les avoir récupérées ?

À titre d'exemple, voici un crochet vraiment horrible de mon application.

function useComponentList(id) {
  const incomingComponents = useSuspenseFetch(
    React.useCallback(() => getComponentAPI().listComponents(id), [id])
  )

  const map = React.useMemo(
    () =>
      Map(
        (incomingComponents || []).map(component => [component.id, component])
      ),
    [incomingComponents]
  )

  return useCacheValue(map)
}

Ce crochet :

  1. Récupère les données à l'aide du rappel donné à partir du point de terminaison donné
  2. Transforme ces données en une carte ImmutableJS - Comme cela est potentiellement coûteux, je mémorise l'opération.
  3. Renvoie la carte enveloppée dans useCacheValue , qui est le bit particulièrement gênant.

useCacheValue ressemble à ceci :

export default function useCacheValue(value) {
  const [state, setState] = React.useState(value)
  React.useEffect(() => {
    setState(value)
  }, [value])

  return [state, setState]
}

l'idée étant qu'il s'agit d'un crochet qui répondra au changement de value (ce qui indique que les données ont été récupérées) mais permet à l'utilisateur de modifier la représentation des applications de réaction de cet état. D'une certaine manière, il agit comme un très mauvais cache (d'où son nom).

J'ai du mal à voir comment ce modèle fonctionne bien avec Redux dans son état actuel. Y a-t-il eu une découverte de ce à quoi cela pourrait ressembler lorsqu'il est écrit par un programmeur qui n'est pas moi et lorsque le suspense est « prêt » pour la récupération de données ? Dans l'état actuel des choses, c'est beaucoup plus laborieux que d'utiliser Redux seul avec des drapeaux de récupération impératifs.

Cela devient probablement beaucoup plus simple une fois que Redux a ses propres crochets, car la principale difficulté à faire jouer les deux ensemble est que Redux utilise un HOC avec un contexte qui n'est pas censé être exposé, mais j'aimerais quand même voir ce que l'officiel la réponse est :)

Suspense est censé fonctionner avec un cache externe ( pas un Hook piloté par l'état). Nous fournirons une implémentation de référence d'un tel cache qui fonctionne pour des cas d'utilisation simples. Relay implémentera son propre mécanisme de mise en cache. Tout autre outil (comme Apollo) pourra également implémenter son propre cache compatible, en s'inspirant éventuellement de ces deux implémentations.

La mutation/l'invalidation n'est pas la seule question qui nécessite des réponses. Nous devons également réfléchir à : quand afficher les spinners, les modèles communs comme « l'indicateur en ligne » qui peut être à l'extérieur de l'arbre suspendu, la coordination des états de chargement (pour les éléments qui doivent se déverrouiller dans un ordre descendant ou entrer comme ils sont ready), rendu en continu des listes, comment cela affecte l'hydratation partielle, et ainsi de suite. Nous travaillons sur ces choses mais il n'y a pas encore de « recommandation officielle » sur aucune d'entre elles. Quand il y en aura, vous le saurez grâce au blog où nous annonçons les mises à jour.

En passant, Suspense pour la récupération de données est un modèle mental suffisamment différent de celui auquel les gens pourraient être habitués. Je ne pense pas qu'il soit juste de s'attendre à ce qu'il soit nécessairement aussi puissant lorsqu'il est intégré à des mécanismes très libres de contraintes comme Redux. Mais on verra. Difficile de dire quoi que ce soit en ce moment.

@gaearon Quand vous dites "nous travaillons sur ces choses", y a-t-il un problème

Merci @gaearon :)

@ntucker Comme toujours, vous pouvez regarder l'activité en cours en tant que PR. Par exemple : https://github.com/facebook/react/pull/14717 , https://github.com/facebook/react/pull/14884 , https://github.com/facebook/react/pull/15061 , https://github.com/facebook/react/pull/15151 , https://github.com/facebook/react/pull/15272 , https://github.com/facebook/react/pull/15358 , https ://github.com/facebook/react/pull/15367 , et ainsi de suite. Nous essayons de mettre des informations descriptives dans chaque PR, et vous pouvez voir les changements de comportement à partir des tests. La barre de documentation pour les expériences est faible pour plusieurs raisons.

Nous publierons des explications plus complètes sur le modèle choisi une fois que nous serons plus sûrs qu'il fonctionne réellement. Je ne pense pas que ce sera productif pour nous ou pour la communauté si nous décrivons minutieusement chaque expérience en détail au fur et à mesure qu'elle se déroule. La plupart de nos premières expériences échouent, et documenter et expliquer chacune d'entre elles ralentirait considérablement notre travail.

C'est encore pire que cela amène souvent les gens à construire un modèle mental autour de quelque chose dont nous réalisons plus tard qu'il ne fonctionne pas de la manière conçue à l'origine. (Comme cela se produit avec maxDuration que nous venons de supprimer.) Nous préférons donc ne pas partager d'idées à moitié cuites jusqu'à ce que ce soit une bonne utilisation de votre temps et de notre temps. Cela est cohérent avec la façon dont nous avons également développé React dans le passé. Quand quelque chose est vraiment prêt (même pour une rédaction théorique du modèle mental), nous concentrerons toute notre attention sur sa documentation et son explication.

En passant, Suspense pour la récupération de données est un modèle mental suffisamment différent de celui auquel les gens pourraient être habitués. Je ne pense pas qu'il soit juste de s'attendre à ce qu'il soit nécessairement aussi puissant lorsqu'il est intégré à des mécanismes très libres de contraintes comme Redux. Mais on verra. Difficile de dire quoi que ce soit en ce moment.

@gaearon , heureusement, le modèle mental de Suspense correspond parfaitement au mien. Très heureux que cette pièce du puzzle se mette en place. Merci pour tout votre travail acharné!

La feuille de route annoncée en novembre dernier (https://reactjs.org/blog/2018/11/27/react-16-roadmap.html) indiquait que la version "concurrente" de Suspense était prévue pour le deuxième trimestre 2019. Q3 2019. Y a-t-il une mise à jour que nous pouvons obtenir en termes de Q3, ou peut-être de Q3, etc. ?

C'était la dernière mise à jour de la feuille de route que j'ai pu trouver : https://reactjs.org/blog/2019/08/08/react-v16.9.0.html#an -update-to-the-roadmap

Nous avons fourni une version expérimentale en octobre : https://reactjs.org/docs/concurrent-mode-intro.html. C'est la même version que nous utilisons en production. Il y a encore du travail à faire (à la fois en termes de peaufinage de l'API et de création d'API de niveau supérieur), mais vous pouvez commencer à jouer avec si vous le souhaitez.

Le suspens me tue

@gaearon Je comprends que vous l'utilisez en production. Mais je suis très réticent à utiliser du code "expérimental" en production. Vous n'êtes pas clair sur la feuille de route, le statut, la progression, les horaires, etc. Est-ce de la qualité alpha, bêta, RC ? Ce terme « expérimental » me dit « ne touchez pas à ça ».

Nous misons tous nos entreprises sur ce code et je suis sûr que nous sommes tous aussi submergés que vous. Un peu de clarté, un blog, QUELQUE CHOSE aiderait vraiment. J'ai presque l'impression que "c'est en production sur Facebook, alors c'est fini".

@mschipperheyn

Il s'agit d'un projet pluriannuel. La réponse honnête est que cela a engendré bien plus de travail que nous ne le pensions lorsque nous avons commencé il y a deux ans.

Mais la bonne nouvelle est que parce que nous l'utilisons maintenant massivement en production, les pièces manquantes sont claires et nous voyons le bout du tunnel. Ce n'est pas théorique - il y a un ensemble fini de choses que nous devons terminer avant de pouvoir confortablement dire qu'il est prêt pour une large adoption.

Voici un état approximatif des différents flux de travail aujourd'hui :

  • <Suspense> API pour le fractionnement de code avec lazy . ( livré dans React 16.6)

    • Comme vous le savez peut-être, vous pouvez déjà utiliser celui-ci.

  • API en mode simultané, par exemple createRoot et useTransition . ( disponible dans les experimental )

    • Solution de compatibilité pour les bibliothèques de type Flux. ( en cours @bvaughn , https://github.com/reactjs/rfcs/pull/147)

    • Changer le modèle prioritaire pour un modèle plus sensé. ( en cours @acdlite , https://github.com/facebook/react/pull/18612)

    • Ne permettez que la dernière transition en attente de se terminer. ( en cours @acdlite)

    • API hors écran ( en cours @lunaruan)

    • Effets de feu lors du masquage/affichage du contenu pour Suspense

    • Effets de feu lors du masquage/affichage du contenu pour Offscreen

    • Afficher et masquer les enfants du portail si nécessaire

    • S'aligner sur les travaux de normalisation en cours pour la planification ( pas commencé )

    • Correction de bugs majeurs connus ( en cours @gaearon et @acdlite)

    • Changer la sémantique des événements. ( en cours @sebmarkbage @trueadm)

    • Déléguer aux racines au lieu du document pour permettre une adoption plus progressive ( en cours , @trueadm)

    • Videz les événements discrets en phase de capture.

    • Envisagez d'obtenir la priorité par défaut de event pour mieux jouer avec le code impératif.

    • Finalisez les autres sémantiques et valeurs par défaut de l'API. ( pas commencé )

    • Mettre à jour les saisies et la documentation.

  • Suspense pour la récupération de données

    • Prise en charge de bas niveau pour signaler qu'un composant n'est pas prêt à être rendu (techniquement disponible dans React stable également, mais cette API n'est pas considérée comme stable).

    • Le moteur de rendu du serveur vide immédiatement les solutions de secours Suspense ( disponibles dans les versions expérimentales)

    • Une solution pour les cas d'utilisation de GraphQL (Relay Hooks, livrés ).

    • Une solution pour les cas d'utilisation non-GraphQL ( en cours @sebmarkbage en collaboration avec Next.js).

    • Une intégration de bundle pour les dépendances basées sur les données. ( en cours )

    • Finalize Blocks API, y compris le contexte.

    • Une solution de mise en cache générique. ( pas commencé )

    • Une sorte d'intégration de routeur.

J'ai presque l'impression que "c'est en production sur Facebook, alors c'est fini".

Je peux voir à quoi cela pourrait ressembler, bien que cette lecture soit un peu démoralisante. :-) Nous avons travaillé sans arrêt dessus pendant tous les mois passés, et de nombreux aspects techniques sont soit terminés, soit sur le point de l'être. La plupart des travaux restants se répartissent en deux catégories :

  • Corriger les défauts que nous avons découverts dans les conceptions initiales avant de les cimenter dans une version stable. Si nous devions sortir ce que nous avons maintenant, nous devrions procéder à des changements importants dans quelques mois. Ce ne serait que déroutant.

  • Compatibilité de l'écosystème et bonnes valeurs par défaut. Cela n'aide pas si nous publions quelque chose que personne ne peut utiliser aujourd'hui parce que cela ne fonctionne pas avec leurs bibliothèques ou leurs approches existantes. Ainsi, le gros du travail (par exemple, la compatibilité avec les bibliothèques de type Flux via useMutableSource , la sélection d'une meilleure sémantique des événements, l'envoi d'une stratégie de mise en cache recommandée) consiste à s'assurer que vous serez réellement en mesure d' utiliser ce que nous avons publié. C'est une longue queue.

En termes de "pouvez-vous utiliser aujourd'hui"... Techniquement, vous pouvez utiliser tout cela aujourd'hui. Nous faisons. Plus précisément, nous utilisons les crochets de relais et le mode simultané. Nous avons encore d'importants changements prévus et des problèmes connus, donc l'état actuel n'atteint pas la barre où nous le considérerions prêt pour une large adoption. Bien sûr, si cela ne vous @experimental comme nous le faisons.

Je ne dirais pas que Facebook est dans une position particulière ici en termes de « finis ». Bien au contraire, nous n'avons pas fini – mais en interne, nous sommes prêts à tolérer le roulement et à construire sur un train en mouvement parce que c'est ainsi que nous savons que ce que nous construisons est solide. Sans ce dogfooding lourd, les défauts que nous avons découverts en six mois prendraient plusieurs années à découvrir et à reconcevoir.

Pour résumer : il y a plus de travail à faire.

@gaearon Merci pour cette mise à jour ! Et je m'excuse si mon ton était faux. J'avoue que j'étais un peu frustré de parcourir Twitter pendant des mois et de ne rien trouver. Cet aspect Server renderer immediately flushes Suspense fallbacks (available in experimental releases) ressemble à quelque chose sur lequel je pourrais consacrer du temps pour le tester avec Apollo Graphql pour notre implémentation.

Oui, il devrait être prêt pour que les auteurs de bibliothèques et les personnes curieuses commencent à jouer avec. Les pièces manquantes visent principalement à fournir des « chemins heureux », mais la majeure partie de la plomberie devrait être là.

Le moteur de rendu du serveur vide immédiatement les solutions de secours Suspense (disponibles dans les versions expérimentales)

Où puis-je lire à ce sujet ? J'espérais une référence d'API en mode simultané (expérimental) mais pas de chance.

Si quelqu'un a une démo assemblant Next.js, les crochets de relais et le mode simultané (avec SSR), ce serait génial. Sinon, je pourrais juste tenter ma chance si je peux trouver une documentation suffisante.

@CrocoDillon

Il n'y a pas de documentation supplémentaire sur le SSR, mais c'est principalement parce qu'il s'agit simplement d'un nouveau comportement par défaut.

Si vous disposez d'une version expérimentale à chaque fois qu'un composant est suspendu sur le serveur, nous vidons à la place la solution de secours Suspense la plus proche. Ensuite, sur le client, vous utiliseriez createRoot(node, { hydrate: true }).render(<App />) .

Notez que cela active déjà toutes les nouvelles fonctionnalités d'hydratation. Ainsi, par exemple, vos limites d'attente seront « attachées » au code HTML de secours généré par le serveur, puis tenteront de rendre le client.

Notez également que vous pouvez commencer à vous hydrater avant le chargement de toute votre application. Lorsque <App> est chargé, vous pouvez vous hydrater. Tant que les composants ci-dessous se suspendent lorsque leur code n'est pas prêt (similaire à paresseux). Ce que React ferait dans ce cas, c'est de conserver le contenu HTML du serveur mais d'y « attacher » la limite Suspense. Lorsque les composants enfants seront chargés, il continuera à s'hydrater. Les parties hydratées deviendraient interactives et rejoueraient des événements.

Vous pouvez probablement demander à @devknoll les prochaines tentatives/exemples d'intégration. Il en a probablement.

Vous pouvez activer le mode simultané dans Next.js en installant react@experimental et react-dom@experimental et en ajoutant ce qui suit à next.config.js

// next.config.js
module.exports = {
  experimental: {
    reactMode: 'concurrent'
  }
}

Voici la discussion Next.js à ce sujet : https://github.com/zeit/next.js/discussions/10645

Est-il possible d'attendre des suspens dans le rendu du serveur (pour des cas tels que la génération de site statique par exemple) ? Je suis d'accord que l'utilisation des rappels est une bonne valeur par défaut, je me demande simplement si c'est annulable ?

Notez également que vous pouvez commencer à vous hydrater avant le chargement de toute votre application. Lorsquea chargé, vous pouvez vous hydrater. Tant que les composants ci-dessous se suspendent lorsque leur code n'est pas prêt (similaire à paresseux). Ce que React ferait dans ce cas, c'est de conserver le contenu HTML du serveur mais d'y « attacher » la limite Suspense. Lorsque les composants enfants seront chargés, il continuera à s'hydrater. Les parties hydratées deviendraient interactives et rejoueraient des événements.

@gaearon voulez-vous dire que vous pouvez rendre un composant normalement sur le serveur, mais utiliser React.lazy sur le client ? Vous permettant de renvoyer le balisage complet à partir du serveur, mais de retarder l'analyse et le rendu du code du composant sur le client. Le balisage rendu par le serveur sert ici de solution de secours pour le suspense ?

@robrichard Je ne l'ai pas vraiment essayé avec React.lazy particulier (nous utilisons un wrapper différent chez FB et Next a également sa propre version) mais je pense que c'est ainsi que cela fonctionnerait. Cela vaut la peine de vérifier :-) Avec certaines limitations - par exemple, si vous mettez à jour ses accessoires et qu'il n'y a pas de plan de sauvetage de mémo ci-dessus, ou si vous mettez à jour le contexte au-dessus, nous devrons le supprimer et afficher la solution de secours car nous ne savons pas quoi faire avec ça.

@gaearon quel est l'état actuel de l'hydratation partielle ? Je sais que #14717 a été fusionné, mais je doute qu'il ait été intégré à une version ?

Il est présent dans chaque version de @experimental depuis longtemps maintenant, tant que vous utilisez l'API unstable_createRoot .

@gaearon pouvez-vous expliquer ce que vous entendez par "dépendances basées sur les données" ?

@gaearon pouvez-vous expliquer ce que vous entendez par "dépendances basées sur les données" ?

Oui bien sûr. Je dois m'excuser pour la brièveté de la liste ci-dessus - elle est très condensée et nombre d'entre eux sont des sous-projets distincts importants (c'est pourquoi ils prennent du temps).

Permettez-moi de prendre du recul et de donner un contexte plus large avant de répondre à votre question spécifique. Le contexte plus large est que la création d'une très bonne solution de récupération de données est vraiment, vraiment difficile. Pas seulement dans le sens de la mise en œuvre mais dans le sens de la conception. En règle générale, il faudrait faire un compromis entre la colocation (en gardant les exigences en matière de données proches de l'endroit où les données sont utilisées) et l'efficacité (à quel moment commençons-nous à charger les données et pouvons-nous éviter les cascades du réseau). Ce n'est pas aussi visible à petite échelle, mais à mesure que le nombre de composants augmente, vous devez vraiment choisir entre d'excellentes performances et un code facile à écrire. Dans de nombreux cas, malheureusement, vous n'obtenez ni l'un ni l'autre - c'est pourquoi la récupération de données en général est un sujet brûlant.

Nous avons une barre très haute pour ce qui entre dans React "officiel". Pour être "Reacty", il doit composer aussi bien que les composants React réguliers. Cela signifie que nous ne pouvons pas de bonne foi recommander une solution qui, selon nous, ne s'adapterait pas à des milliers de composants. Nous ne pouvons pas non plus recommander une solution qui vous oblige à écrire du code de manière alambiquée et optimisée pour qu'il reste performant. Chez FB, nous en avons tiré beaucoup de leçons de l'équipe Relay. Nous savons que tout le monde ne peut pas utiliser GraphQL, ou ne voudrait pas utiliser Relay (ce n'est pas en soi très populaire et l'équipe ne l'a pas optimisé pour une adoption externe). Mais nous voulons nous assurer que notre solution de récupération de données pour React général intègre les leçons durement acquises de Relay et ne souffre pas d'avoir à choisir entre performances et colocation.

Je tiens à souligner qu'il ne s'agit pas seulement de grosses applications. Les problèmes sont plus visibles dans les grosses applications, mais les petites applications qui importent un tas de composants à partir de npm souffrent également d'un sous-ensemble de ces inefficacités. Comme envoyer trop de code côté client et le charger dans une cascade. Ou charger trop d'avance. De plus, les petites applications ne restent pas éternellement de petites applications. Nous voulons une solution qui fonctionne parfaitement pour une application de toute taille, tout comme le modèle de composant React fonctionne de la même manière quelle que soit la complexité de votre application.

Maintenant, pour répondre à votre question spécifique. Relay a une fonctionnalité appelée "dépendances basées sur les données". Une façon d'y penser est une évolution de la dynamique import . Dynamique import n'est pas toujours efficace. Si vous souhaitez charger du code uniquement lorsqu'une condition est vraie (par exemple "l'utilisateur est-il connecté" ou "l'utilisateur a-t-il des messages non lus"), votre seule option est de le déclencher paresseusement. Mais cela signifie que vous « lancez » la récupération (comme avec React.lazy ) uniquement lorsque quelque chose est utilisé. C'est en fait trop tard. Par exemple, si vous avez plusieurs niveaux de composants à code divisé (ou de composants en attente de données), le plus interne ne commencera à se charger qu'après le chargement de celui au-dessus. C'est inefficace et c'est une « cascade » de réseau. Le relais "dépendances basées sur les données" vous permet de spécifier les modules que vous souhaitez récupérer dans le cadre de la requête. C'est-à-dire "si une condition est vraie, incluez ce morceau de code avec la réponse de données". Cela vous permet de charger tous les morceaux de code fractionné dont vous aurez besoin le plus tôt possible. Vous n'avez pas à échanger la colocation contre la performance. Cela peut sembler peu grave, mais cela a réduit le nombre de secondes littérales dans le code du produit.

Maintenant, encore une fois, nous ne mettons pas Relay dans React, et nous ne voulons pas forcer les gens à utiliser GraphQL. Mais conceptuellement, la fonctionnalité elle-même est générique, et avoir une bonne solution open source pour cela permettrait aux gens de faire beaucoup plus de fractionnement de code qu'aujourd'hui (et donc d'envoyer beaucoup moins de code JS client !) Cette fonctionnalité générique ne s'appellera pas "dépendances basées sur les données" - c'est juste un nom de relais auquel j'ai fait référence. Cette fonctionnalité fera partie d'une solution recommandée plus large qui ne nécessite pas GraphQL. Je viens de l'appeler par ce nom dans la liste parce que c'était beaucoup à expliquer pour un seul point de liste à puces.

J'espère que cela le clarifie.

Cette page vous a été utile?
0 / 5 - 0 notes