React-window: Modifications de la version 2

Créé le 29 juil. 2019  ·  44Commentaires  ·  Source: bvaughn/react-window

Ceci est un problème général pour partager mes plans pour la prochaine version 2.0 de react-window .

Les commentaires sont appréciés et seront pris en considération. Je vous demande de comprendre si je ne suis pas en mesure de répondre à toutes les demandes. Je vais essayer de faire de mon mieux pour évaluer les demandes de fonctionnalités par rapport à la taille du bundle, aux performances d'exécution et aux problèmes de maintenance.

Je pense que la mise à niveau de la version 1 à la version 2 peut nécessiter des changements de code substantiels , dont beaucoup ne seront pas possibles à automatiser avec des mods de code. Pour cette raison, en particulier pour le code d'application, je vous déconseille de mettre à niveau le code existant à moins que vous n'ayez une bonne raison (par exemple, vous avez besoin de la prise en charge du contenu de taille dynamique).

Je vais également épingler les documents actuels sur le domaine react-window-v1.now.sh afin qu'ils ne soient pas perdus lors de la mise à jour pour la version 2.


Table des matières:
  • Prend en charge moins de composants
  • Utiliser l'API des accessoires de rendu
  • Fini le support des listes horizontales
  • Seules les grilles prennent en charge RTL
  • Modifications du délai de rappel de onScroll

    * Autres changements / dépréciations

Moins de composants

Une façon de gérer la complexité consiste à réduire le nombre de composants pris en charge par la bibliothèque . Je prévois actuellement de prendre en charge uniquement les types de composants suivants dans la version 2:

  • SimpleList (auparavant FixedSizeList )

    • Ce composant de liste hautement optimisé doit être utilisé lorsque les hauteurs de ligne sont fixes (et connues à l'avance).

  • List (auparavant DynamicSizeList )

    • Cette liste doit être utilisée pour le contenu de taille dynamique (par exemple, chat, fil d'actualité). Il nécessite l'API ResizeObserver (ou polyfill).

  • Grid (auparavant VariableSizeGrid )

    • Ce composant doit être utilisé pour les données tabulaires (par exemple les feuilles de calcul) qui doivent être virtualisées le long des axes vertical et horizontal. Il prend en charge les lignes et les colonnes de taille variable, mais ne prend pas en charge la mesure et la mise à jour automatiques de leurs tailles.


Rendre les accessoires

L'un des changements majeurs de react-virtualized à react-window été la décision de traiter children comme des éléments React (par exemple React.createElement(children, props)) ) plutôt que comme des accessoires de rendu (par exemple children(props) ).

Il y avait quelques motivations pour faire cela:

  • React fournit des solutions intégrées pour la mémorisation (par exemple React.memo , useMemo , shouldComponentUpdate ) donc je n'ai pas eu besoin d'implémenter ma propre abstraction de mise en cache pour les rendus d'éléments.
  • Les API comme les hooks et le suspense "fonctionnent simplement" à l'intérieur des moteurs de rendu d'élément.
  • Les clés peuvent être gérées par react-window sans avoir besoin de l'accessoire de rendu pour les transmettre (et sans nécessiter d'appels cloneElement ).

Malheureusement, il y avait aussi quelques inconvénients:

  • Les moteurs de rendu d'éléments en ligne coûtent cher. Parce que leur "type" (la définition de la fonction) est recréé à chaque fois que le composant parent est rendu, React démonte et remonte profondément son arbre rendu. Cela signifie que les documents doivent apprendre aux gens à ne pas les utiliser, même s'ils sont souvent plus pratiques.
  • Étant donné que les fonctions en ligne ne pouvaient pas être utilisées pour fermer sur une portée locale, il était plus compliqué pour les moteurs de rendu d'élément de partager l'état avec les parents, nécessitant des API telles que itemData et une exportation de comparaison personnalisée areEqual .

Après avoir pris en compte les avantages et les inconvénients ci-dessus, j'ai décidé de passer également à une approche d'accessoires de rendu pour react-window . Cela signifie que des exemples compliqués comme celui-ci peuvent être réécrits plus facilement:

const Example = ({ height, items, toggleItemActive, width }) => (
  <List
    height={height}
    itemCount={items.length}
    itemRenderer={({ index, key, style }) => {
      const item = items[index];
      return (
        <div key={key} onClick={() => toggleItemActive(index)} style={style}>
          {item.label} is {item.isActive ? "active" : "inactive"}
        </div>
      );
    }}
    itemSize={35}
    width={width}
  />
);

Plus de support de liste horizontale

Auparavant, les composants de liste prenaient en charge les modes de disposition horizontal et vertical. Afin de simplifier la mise en œuvre et la maintenance, et parce que le cas d'utilisation extrêmement courant est celui des listes verticales, je supprimerai le support pour layout="horizontal" .


Prise en charge RTL

Les composants de grille continueront à prendre en charge direction="RTL" , mais pas les listes (puisqu'ils ne prendront en charge qu'une disposition verticale). Ce compromis est fait pour permettre aux listes d'être plus petites et plus faciles à maintenir.


onItemsRendered et onScroll changements de rappel

Les composants de liste et de grille prennent actuellement en charge les accessoires de rappel onItemsRendered et onScroll . Ces rappels sont appelés pendant la phase de validation (une fois que la liste ou la grille a terminé le rendu). Cela peut être utile dans la mesure où il est toujours sûr d'effectuer un effet secondaire (comme la journalisation des analyses) en réponse à ces rappels, mais cela présente également un inconvénient: toute mise à jour synchronisée par défilement doit être effectuée dans un second rendu ("en cascade") .

La version 2 apportera une modification au rappel onScroll pour résoudre ce problème. Le rappel onScroll sera appelé pendant le cycle de distribution de l'événement afin que toute mise à jour soit groupée (par React) avec la propre mise à jour de la liste ou de la grille.

Le rappel onItemsRendered sera remplacé par un accessoire onItemsDisplayed , bien qu'il continuera à être appelé pendant le cycle de validation. Cette modification est apportée pour permettre au composant de liste d'optimiser de manière plus agressive les performances de rendu en effectuant un pré-rendu à la priorité d'inactivité et en utilisant des API expérimentales telles que le verrouillage d'affichage .


Autres modifications / dépréciations d'accessoires

Il y a plusieurs obsolètes en attente (avec des avertissements DEV) qui seront supprimées:

  • innerTagName et outerTagName pour tous les composants de la liste et de la grille. (Utilisez à la place innerElementType et outerElementType .)
  • overscanCount , overscanColumnsCount et overscanRowsCount pour le composant de grille. (Utilisez à la place overscanColumnCount et overscanRowCount .)
  • overscanCount sera supprimé pour les composants de liste, au profit d'une approche de surbalayage dynamique.
  • Valeurs "horizontale" et "verticale" pour direction . (Ceux-ci ont été déplacés vers layout , mais ils seront entièrement supprimés dans la version 2.)
  • Le prop itemData (et le prop data passé aux moteurs de rendu d'élément) seront supprimés car la modification d'une API de prop de rendu ne le rend plus nécessaire.
  • Le prop useIsScrolling (et le prop isScrolling passé aux moteurs de rendu d'élément) seront supprimés car les modifications apportées au pré-rendu et au verrouillage d'affichage rendraient la mise en œuvre plus coûteuse.
  • Les paramètres d'alignement du défilement changeront légèrement. Le "auto" précédemment nommé sera désormais nommé "minimal". La nouvelle valeur par défaut sera "smart" (plutôt que "auto").

Notez que certains des accessoires obsolètes ci-dessus peuvent ne pas être toujours pertinents compte tenu des autres changements prévus, mais je les énumère quand même ici par souci d'exhaustivité.

👋 help wanted 💬 discussion

Commentaire le plus utile

Les listes horizontales sont largement utilisées sur mobile dans notre cas. Nous les utilisons également pour un carrousel à défilement infini, comme le contrôle. L'OMI doit avoir quelque chose sur mobile.

Tous les 44 commentaires

Les listes horizontales sont largement utilisées sur mobile dans notre cas. Nous les utilisons également pour un carrousel à défilement infini, comme le contrôle. L'OMI doit avoir quelque chose sur mobile.

Merci d'avoir partagé un cas d'utilisation @istarkov. Ce n'est pas que je ne pense pas qu'il existe des cas d'utilisation valides pour le fenêtrage horizontal. Je pense simplement qu'ils sont beaucoup moins courants. (Même dans le cas des carrousels, beaucoup utilisent la navigation par flèches gauche / droite qui ne nécessite pas de fenêtrage basé sur les événements de "défilement".) Je pense que cela pourrait être le meilleur moyen (pour moi) de supprimer la prise en charge de la v2 pour aider à compenser certains de la complexité que je prévois d'introduire avec le pré-rendu, le dimensionnement dynamique, etc.

Je suis vraiment enthousiasmé par cette approche allégée qui, espérons-le, mènera à un code plus simple, plus performant et plus simple.

Génial. Mais j'ai peu de soucis à propos de la suppression de la liste de taille variable. Vous prévoyez de remplacer la liste de taille variable par DynamicList, mais le problème avec la liste dynamique que vous ne pouvez pas faire défiler jusqu'à l'élément, ce qui pourrait être une fonctionnalité très utile pour certains composants et une telle exigence pourrait survenir au fil du temps, vous ne pouvez donc pas prédire si react-window répond à vos besoins.
Le deuxième problème que je vois concerne les performances de la liste dynamique, si vous pouvez fournir les mêmes performances pour la liste dynamique que pour la liste de taille variable, il peut être correct de la supprimer même si vous ne supportez pas scrollToItem, mais sinon, les développeurs pourraient être verrouillés situations étranges où la liste dynamique est lente et n'a pas de défilement jusqu'à la prise en charge des éléments, la liste n'a que la hauteur des éléments fixe.

Vous prévoyez de remplacer la liste de taille variable par DynamicList, mais le problème avec la liste dynamique que vous ne pouvez pas faire défiler jusqu'à l'élément

Je ne pense pas que ce soit une limitation inhérente, juste une des implémentations actuelles. J'ai des idées sur la façon dont je pourrais offrir cette fonction. Si je trouve le temps de m'y attaquer, c'est une autre question: sourire:

Le deuxième problème que je vois concerne les performances de la liste dynamique, si vous pouvez fournir les mêmes performances pour la liste dynamique que pour la liste de taille variable, il peut être correct de la supprimer même si vous ne supportez pas scrollToItem, mais sinon, les développeurs pourraient être verrouillés situations étranges où la liste dynamique est lente et n'a pas de défilement jusqu'à la prise en charge des éléments, la liste n'a que la hauteur des éléments fixe.

Difficile de dire si cela fonctionnera aussi bien. On dirait que la liste dynamique devra faire plus de travail, il est donc probable qu'elle ne fonctionnera pas aussi bien. Peut-être que la différence sera significative, peut-être pas. Je veux pouvoir prendre en charge certaines choses que je ne fais pas actuellement, et je pense que je dois réduire la portée pour ajouter de nouvelles fonctionnalités. Si vous êtes actuellement satisfait de la liste des variables, il n'y a aucune raison de passer à la v2 (du moins de si tôt).

@bvaughn Cela ressemble à de la documentation pour moi!
Avez-vous travaillé là-dessus depuis l'été dernier? ;-)

Sur une note plus sérieuse - je pense que les accessoires de rendu ont du sens dans ce contexte, même si je ne suis pas fan.

Non, j'ai écrit ceci ce matin 😝 Je suis épuisé.

Je pense que les accessoires de rendu ont du sens dans ce contexte, même si je ne suis pas fan.

Pouvez-vous expliquer pourquoi vous n'êtes pas fan?

La prise en charge de la liste horizontale / grille pourrait-elle avoir un sens en tant que fonctionnalité optionnelle telle que AutoSizer (react-virtualized-auto-sizer)?

J'ai utilisé à la fois react-virtualized et react-window pour les listes horizontales, et j'ai trouvé l'API react-window beaucoup plus simple. Bien que je comprenne la nécessité de la dépréciation dans l'espoir d'une API plus simple.

La prise en charge du réseau est toujours prévue. Optez pour le support horizontal, non pas vraiment. Je ne pense pas que cela aurait du sens.

@bvaughn J'apprécie généralement les accessoires de rendu et ils résoudront les problèmes que vous avez décrits, mais je pense qu'ils encouragent une fonction en ligne qui peut ou non contenir un tas de logique imbriquée. 🤔 Tout défaut incombe ici à l'utilisateur. 🙂

pouvez-vous réaliser une grille de maçonnerie?

@nikitapilgrim Non. Je suggérerais simplement d'utiliser le composant Masonry de react-virtualized

https://github.com/bvaughn/react-virtualized/blob/master/docs/Masonry.md

merci, mais son travail uniquement avec réagit-virtualisé?

@nikitapilgrim Yup. 👍
React-virtualized prend en charge un tas de fonctionnalités, ce que react-window ne fait pas.

La portée de réagir fenêtre est considérablement réduite, de se concentrer à rendre le paquet plus petit et plus rapide. 😉

Si vous avez besoin de fonctionnalités de react-virtualized, je vous suggère de vous en tenir à cela - c'est toujours une excellente bibliothèque!

Je suis tombé sur react-window parce que je cherchais une solution à ce problème react-virtualized Masonry mais je ne peux plus après la mise babel jour de

Ce n'est pas le lieu de signaler les problèmes avec react-virtualized.

D'accord @bvaughn. Cependant, vous-même et @babangsund ont répondu à @nikitapilgrim ci-dessus qu'un composant Masonry ne sera pas introduit dans react-window et à la place d'utiliser react-virtualized . Cependant, si un utilisateur est sur les derniers [email protected] et [email protected] (comme avec create-react-app ), react-virtualized ne fonctionnera pas nécessairement.

Je pense que c'est une information utile pour quiconque descend dans le même terrier de lapin.
¯ \ _ (ツ) _ / ¯

hey je veux utiliser la liste de taille dynamique où puis-je télécharger la version 2 ou devrai-je utiliser react virtualise?
image

voici à quoi ressemble ma liste avec une liste de taille variable

Ce n'est pas un problème de support générique. Veuillez garder les commentaires sur le sujet.

Les commentaires sont appréciés

J'utilise react-window sur un produit de type trello et voici quelques réflexions:

Rendre les accessoires

Cela semble être un bon changement en raison de la simplicité et pour éviter l'inconvénient mentionné. En outre, l'API serait plus similaire à FlatList de react-native. Je me souviens avoir lu la discussion sur https://github.com/bvaughn/react-window/issues/85.

Moins de composants
Plus de support de liste horizontale

Je vote fortement contre la suppression de horizontal support et VariableSizeList . Comme vous pouvez l'imaginer, ce sont les deux principaux que j'utilise. Leur mise en œuvre est-elle vraiment trop lourde à maintenir? Sinon, j'espère que vous pourrez les reconsidérer et les conserver.

Je n'ai pas d'opinions tranchées sur les autres changements. La suppression de overscanCount m'inquiète un peu, mais je n'ai pas encore rencontré de cas d'utilisation où une valeur personnalisée était encore requise, donc c'est probablement bien.

Salut @bvaughn! Merci pour ce package! Je cherche à intégrer la version 2 dans mon projet au travail. Avez-vous une idée approximative du moment où cela pourrait être publié?

Merci pour cette bibliothèque et le partage de votre plan pour la future version est très utile pour nous aider à atténuer la dette technique.

Existe-t-il un moyen "simple" d'avoir WindowScroller comportement react-window et les versions ultérieures de la version 2?

Si ce n'est pas possible, serait-ce hors du périmètre de cette version 2? ou cela pourrait-il être ajouté plus tard?

Mon contexte est que ma mise en page comprend un pied de page et que l'utilisation d'une approche moderne comme DynamicSizeList introduirait une deuxième barre de défilement (une pour la page et une pour la liste des produits)

Excellent package. J'attends avec impatience les listes de hauteur dynamiques par défaut - pour le moment, j'ai écrit un tas de logique personnalisée pour renvoyer les hauteurs de ligne rendues à la liste parente. J'espère qu'avec cette nouvelle version, je pourrai supprimer cette logique. Merci pour votre travail là-dessus!

@ltkn @mrdanimal

Il existe déjà un moyen d'utiliser le défilement de la fenêtre:
https://github.com/bvaughn/react-window/issues/30#issuecomment -428868071

Comment faire Scroll infini dans les deux sens, à gauche ou à droite !!!

Si nous avons WindowScroller sans dépend de react-virtualized ce sera génial. Parce que l'objectif derrière react-window rendait beaucoup plus efficace et moins de code que react-virtualized Donc, je ne veux pas utiliser WindowScroller partir de react-virtualized . Au lieu de cela, cherchez un package séparé comme react-virtualized-auto-sizer .

Merci d'avance.

@prabusamvel hm ..
Quel est l'avantage d'un package séparé?

J'ai joué avec le nouveau DynamicSizeList. Très cool! Je pense qu'une grande amélioration serait d'inclure «ttb» et «btt» (de haut en bas, de bas en haut) dans le type de direction. Il n'existe actuellement aucun moyen propre d'implémenter une liste qui défile vers le haut, mais toutes les autres directions sont prises en charge.

@toddmacintyre Je ne trouve pas cette version 2. Quelqu'un peut-il me guider?

@muhammedmagdi npm install react-window@next

Ce serait génial si la version 2 pouvait prendre en charge les structures DOM requises par la spécification ici - https://www.w3.org/TR/wai-aria-1.1/#grid car # 217 est toujours un problème pour nous. Autant que je sache, votre proposition pour la version 2 ne l'est pas actuellement.

@mjurkowski @bvaughn yarn add react-window@next installe 1.6.0-alpha.1 . Aussi, lorsque vous essayez d'exécuter l'exemple de sandbox de liste dynamique https://react-window-next.now.sh/#/examples/list/dynamic -size, il lance Error importing GitHub repository: Could not find package.json

Que diriez-vous de passer le index dans Grid aussi - pendant que vous y êtes? :)

Une partie de notre application nécessite une grille avec des en-têtes de colonne à largeur variable. Nous y sommes parvenus en utilisant une liste de taille variable horizontale couplée à une grille et en synchronisant le défilement des deux.

La suppression des listes horizontales nous empêchera de créer cette interface utilisateur (ou du moins nous devrons la réécrire pour utiliser 2 grilles où la grille d'en-tête de colonne a une seule ligne.

Le produit suivant a l'air incroyable. Mais j'ai besoin à la fois d'horizontal et de vertical, donc pour info, j'ai créé le mien: https://www.npmjs.com/package/react-infinite-grid-scroller. Utilise la disposition de la grille, réagit aux hooks, IntersectionObserver et requestIdleCallback.

Vos commentaires sont les bienvenus.

J'ai le sentiment que le support des éléments collants serait un excellent ajout à react-window. C'est un cas d'utilisation assez courant et serait simple à implémenter pour les listes et les grilles.

L'API pourrait ressembler à ceci:

<Grid
    // First 2 columns are sticky
    stickyLeft={2}
    // Last column is not sticky (default value)
    stickyRight={0}
    // First and last rows are sticky
    stickyTop={1}
    stickyBottom={1}
/>

Les deux éléments clés pour faire fonctionner l'adhérence sont:

  1. ne démontez les cellules collantes que si elles sont hors de la fenêtre dans l'axe elles ne sont pas collantes
  2. utilisez position: sticky au lieu de absolute , et utilisez margin-x au lieu de left et top pour l'axe qui n'est pas collant

Le coût d'une si grande fonctionnalité semble raisonnable:

  • L'empreinte est minime
  • Aucun impact majeur sur les performances (juste restituer quelques lignes / colonnes supplémentaires)
  • Le support du navigateur est excellent, et ceux qui ne prennent pas en charge position: sticky voient juste une version normale

Si vous pensez que ce cas d'utilisation est trop spécifique pour être pris en charge tel quel, un excellent compromis serait de ne prendre en charge que le point 1. Pouvoir spécifier si une cellule doit être rendue ou non permettrait d'implémenter facilement la stickiness.

Je serais heureux d'aider si nécessaire.

ne prend pas en charge la mesure et la mise à jour automatiques de leurs tailles.

J'ai l'impression que c'est un gros inconvénient. Pour presque toutes les grilles que j'ai écrites, j'ai besoin de 3 ou 4 colonnes de largeur fixe (pour une étiquette de statut, des métadonnées, un appel à l'action, etc.) et 1 colonne de largeur dynamique qui occupe le reste de l'espace disponible.

Je comprends que "ne prend pas en charge" ne signifie pas nécessairement que cela ne sera pas possible avec l'ajout de code supplémentaire et de composants comme Autosizer - ce serait juste bien d'avoir ces cas d'utilisation bien considérés et des solutions documentées pour ceux qui ont besoin d'un colonne dynamique mais ne veulent pas aller pour réagir-virtualisé pour tous les bagages qu'il apporte.

ce serait juste bien d'avoir ces cas d'utilisation bien considérés et des solutions documentées pour ceux qui ont besoin d'une colonne dynamique

Totalement compris - mais pratiquement parlant, cela demanderait beaucoup d'efforts , et cette bibliothèque a été un travail d'amour (pas une entreprise rémunérée). Malheureusement , je ne l' ai pas encore eu le temps de terminer mes efforts scope vers le

ce serait juste bien d'avoir ces cas d'utilisation bien considérés et des solutions documentées pour ceux qui ont besoin d'une colonne dynamique

Totalement compris - mais pratiquement parlant, cela demanderait beaucoup d'efforts , et cette bibliothèque a été un travail d'amour (pas une entreprise rémunérée). Malheureusement, je n'ai même pas eu le temps de terminer mes efforts de _scoped down_ v2, sans parler de quelque chose de plus agressif. 😞

Ouais. Je comprends ça. J'espère que ce genre d'efforts pourra être mené par la communauté.

Ce serait bien - mais d'après mon expérience, cela n'arrive jamais: sourire:

Je n'ai pas pu utiliser WindowScroller avec DynamicSizedList, probablement à cause du rendu juste à temps faisant que scrollTo ne fonctionne pas très bien. Cela sera-t-il possible avec la nouvelle version?

J'ai accepté le fait que je n'ai ni le temps ni l'énergie pour terminer cet effort. Si quelqu'un souhaite intervenir et terminer la branche que j'ai créée, je serais ravi de votre aide. (Veuillez également consulter le numéro 6 pour plus de détails sur les List et Grid devraient être implémentés pour prendre en charge les mesures juste à temps.)

Salut @bvaughn ,
J'ai créé une discussion sur ma fourchette avec quelques notes aléatoires.
Faites-moi savoir s'il y a quelque chose qui ne devrait pas figurer sur la liste ou qui n'est pas correct. Je terminerai la liste quand je ferai des progrès.

On dirait de bonnes choses

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