React-window: Cambios en la versión 2

Creado en 29 jul. 2019  ·  44Comentarios  ·  Fuente: bvaughn/react-window

Este es un tema general para compartir mis planes para la próxima versión 2.0 de react-window .

Se agradecen los comentarios y se los tendrá en cuenta. Le pido que sea comprensivo si no puedo atender todas las solicitudes. Intentaré hacer todo lo posible para sopesar las solicitudes de funciones con el tamaño del paquete, el rendimiento en tiempo de ejecución y las preocupaciones de mantenimiento.

Espero que la actualización de la versión 1 a la 2 requiera cambios sustanciales en el código , muchos de los cuales no serán posibles de automatizar con modificaciones de código. Debido a esto, particularmente para el código de la aplicación, desaconsejaría actualizar el código existente a menos que tenga una razón sólida (por ejemplo, si necesita soporte para contenido de tamaño dinámico).

También voy a seguir adelante y anclar los documentos actuales al dominio react-window-v1.now.sh para que no se pierdan cuando actualice a la versión 2.


Tabla de contenido:
  • Admite menos componentes
  • Utilice la API de accesorios de renderizado
  • No más soporte de listas horizontales
  • Solo las cuadrículas admiten RTL
  • Cambios en el tiempo de devolución onScroll llamada de

    * Otros cambios / depreciaciones

Menos componentes

Una forma de ayudar a gestionar la complejidad es reducir la cantidad de componentes que admite la biblioteca . Actualmente planeo admitir solo los siguientes tipos de componentes en la versión 2:

  • SimpleList (anteriormente FixedSizeList )

    • Este componente de lista altamente optimizado debe usarse cuando las alturas de fila son fijas (y conocidas de antemano).

  • List (anteriormente DynamicSizeList )

    • Esta lista debe usarse para contenido de tamaño dinámico (por ejemplo, chat, suministro de noticias). Requiere la API ResizeObserver (o polyfill).

  • Grid (anteriormente VariableSizeGrid )

    • Este componente debe usarse para datos tabulares (por ejemplo, hojas de cálculo) que deben virtualizarse a lo largo de los ejes vertical y horizontal. Admite filas y columnas de tamaño variable, pero no admite la medición y actualización automática de sus tamaños.


Accesorios de renderizado

Uno de los principales cambios de react-virtualized a react-window fue la decisión de tratar children como elementos de React (por ejemplo, React.createElement(children, props)) ) en lugar de como accesorios de renderización (por ejemplo, children(props) ).

Hubo un par de motivaciones para hacer esto:

  • React proporciona soluciones integradas para la memorización (por ejemplo, React.memo , useMemo , shouldComponentUpdate ) por lo que no tuve que implementar mi propia abstracción de almacenamiento en caché para los renderizadores de elementos.
  • Las API como los ganchos y el suspenso "simplemente funcionan" dentro de los procesadores de elementos.
  • Las claves pueden ser administradas por react-window sin requerir que el accesorio de renderizado las pase (y sin requerir llamadas cloneElement ).

Desafortunadamente, también hubo algunas desventajas:

  • Los procesadores de elementos en línea incurren en un alto costo. Debido a que su "tipo" (la definición de la función) se recrea cada vez que el componente principal se procesa, React desmonta y vuelve a montar profundamente su árbol procesado. Esto significa que los documentos deben enseñar a las personas a no usarlos, aunque a menudo son más convenientes.
  • Debido a que las funciones en línea no se podían usar para cerrar sobre el alcance local, era más complicado para los renderizadores de elementos compartir el estado con los padres, requiriendo API como itemData y una exportación de comparación personalizada areEqual .

Después de tener en cuenta los pros y los contras anteriores, he decidido convertirme a un enfoque de react-window también. Esto significa que los ejemplos complicados como este se pueden reescribir más fácilmente:

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}
  />
);

No más soporte de lista horizontal

Anteriormente, los componentes de lista admitían modos de diseño tanto horizontal como vertical. Para simplificar la implementación y el mantenimiento, y debido a que el caso de uso abrumadoramente común son las listas verticales, eliminaré el soporte para layout="horizontal" .


Soporte RTL

Los componentes de la cuadrícula seguirán admitiendo direction="RTL" , pero las listas no lo harán (ya que solo admitirán un diseño vertical). Esta compensación se realiza para permitir que las listas sean más pequeñas y más fáciles de mantener.


onItemsRendered y onScroll cambios de devolución

Los componentes de lista y cuadrícula actualmente admiten accesorios de devolución onScroll llamada onItemsRendered y onScroll . Estas devoluciones de llamada se invocan durante la fase de confirmación (después de que la lista o cuadrícula haya terminado de renderizarse). Esto puede ser útil porque siempre es seguro realizar un efecto secundario (como el registro de análisis) en respuesta a estas devoluciones de llamada, pero también tiene una desventaja: cualquier actualización sincronizada de desplazamiento debe realizarse en un segundo procesamiento ("en cascada") .

La versión 2 hará un cambio en la devolución de llamada onScroll para solucionar este problema. Se llamará a la devolución onScroll llamada para que cualquier actualización sea agregada (por React) con la lista o la propia actualización de la cuadrícula.

La devolución onItemsRendered llamada onItemsDisplayed prop , aunque seguirá llamándose durante el ciclo de confirmación. Este cambio se está realizando para permitir que el componente de lista optimice de manera más agresiva el rendimiento del renderizado mediante el renderizado previo con prioridad inactiva y el uso de API experimentales como el bloqueo de pantalla .


Otros cambios de accesorios / depreciaciones

Hay varias bajas pendientes (con advertencias de DEV) que se eliminarán:

  • innerTagName y outerTagName para todos los componentes de lista y cuadrícula. (Utilice innerElementType y outerElementType lugar).
  • overscanCount , overscanColumnsCount y overscanRowsCount para el componente de cuadrícula. (Utilice overscanColumnCount y overscanRowCount lugar).
  • overscanCount se eliminarán para los componentes de la lista, a favor de un enfoque de sobreexploración dinámica.
  • Valores "horizontal" y "vertical" para direction . (Se movieron a layout , pero se eliminarán por completo en la versión 2.)
  • El itemData prop (y el correspondiente data prop pasado a los renderizadores de elementos) se eliminarán porque el cambio a una API de render prop ya no lo hace necesario.
  • El useIsScrolling prop (y el correspondiente isScrolling prop pasado a los renderizadores de elementos) se eliminarán porque los cambios en la representación previa y el bloqueo de la pantalla harían que su implementación sea más cara.
  • Los parámetros de alineación de desplazamiento cambiarán ligeramente. El "auto" anteriormente denominado ahora se denominará "mínimo". El nuevo valor predeterminado será "inteligente" (en lugar de "automático").

Tenga en cuenta que algunos de los accesorios obsoletos anteriores pueden no ser relevantes dados los otros cambios planeados, pero los enumero aquí de todos modos para completarlos.

👋 help wanted 💬 discussion

Comentario más útil

Las listas horizontales se utilizan mucho en el móvil en nuestro caso. También los usamos para un carrusel de desplazamiento infinito como control. OMI debe tener algo en el móvil.

Todos 44 comentarios

Las listas horizontales se utilizan mucho en el móvil en nuestro caso. También los usamos para un carrusel de desplazamiento infinito como control. OMI debe tener algo en el móvil.

Gracias por compartir un caso de uso @istarkov. No es que no crea que haya _ ningún_ caso de uso válido para el sistema de ventanas horizontal. Creo que son mucho menos comunes. (Incluso en el caso de los carruseles, muchos usan la navegación de flecha izquierda / derecha que no requiere ventanas basadas en eventos de "desplazamiento"). Creo que aún podría ser la mejor ruta (para mí) para eliminar el soporte para v2 para ayudar a compensar algunos de la complejidad que planeo introducir con la representación previa, el tamaño dinámico, etc.

Estoy realmente emocionado por este enfoque más ágil que, con suerte, conducirá a un código más simple, más eficiente y más simple.

Estupendo. Pero tengo pocas preocupaciones acerca de eliminar la lista de tamaños variables. Está planeando reemplazar la lista de tamaño variable con DynamicList, pero el problema con la lista dinámica es que no puede desplazarse al elemento, que podría ser una característica bastante útil para algunos componentes y tal requisito podría surgir con el tiempo, por lo que no puede predecir react-window se adapta a sus necesidades.
El segundo problema que veo es el rendimiento de la lista dinámica, si puede proporcionar el mismo rendimiento para la lista dinámica que para la lista de tamaño variable, podría estar bien eliminarlo incluso si no es compatible con scrollToItem, pero si no, los desarrolladores podrían estar bloqueados situaciones extrañas en las que la lista dinámica es lenta y no tiene desplazamiento al soporte de elementos, la lista solo tiene una altura de elementos fija.

Está planeando reemplazar la lista de tamaño variable con DynamicList, pero el problema con la lista dinámica es que no puede desplazarse al elemento

No creo que esta sea una limitación inherente, solo una de la implementación actual. Tengo ideas sobre cómo podría ofrecer esa función. Si encuentro tiempo para abordarlo es otra cuestión: sonríe:

El segundo problema que veo es el rendimiento de la lista dinámica, si puede proporcionar el mismo rendimiento para la lista dinámica que para la lista de tamaño variable, podría estar bien eliminarlo incluso si no es compatible con scrollToItem, pero si no, los desarrolladores podrían estar bloqueados situaciones extrañas en las que la lista dinámica es lenta y no tiene desplazamiento al soporte de elementos, la lista solo tiene una altura de elementos fija.

Es difícil decir si funcionará también. Parece que la lista dinámica tendrá que hacer más trabajo, por lo que es probable que no funcione tan bien. Quizás la diferencia sea significativa, quizás no. Quiero poder admitir algunas cosas que no hago actualmente, y creo que necesito recortar el alcance para agregar nuevas funciones. Sin embargo, si actualmente está satisfecho con la lista de variables, no hay razón para actualizar a v2 (al menos en el corto plazo).

@bvaughn ¡ Esto me parece documentación!
¿Has estado trabajando en esto desde el verano pasado? ;-)

En una nota más seria, creo que los accesorios de renderización tienen sentido en este contexto, aunque no soy un fanático.

No, escribí esto esta mañana. Estoy agotado.

Creo que los accesorios de renderización tienen sentido en este contexto, aunque no soy un fan.

¿Puedes explicar por qué no eres fan?

¿Podría tener sentido el soporte de lista / cuadrícula horizontal como una característica opcional como AutoSizer (react-virtualized-auto-sizer)?

He usado tanto react-virtualized como react-window para listas horizontales, y encuentro la API de react-window mucho más simple. Aunque definitivamente entiendo la necesidad de la desaprobación con la esperanza de una API más simple.

El soporte de red todavía está planeado. Opta por el soporte horizontal, no, en realidad no. No creo que eso tenga sentido.

@bvaughn Generalmente disfruto de los accesorios de renderizado y resolverán los problemas que ha descrito, pero creo que fomentan una función en línea que puede contener o no un montón de lógica anidada. 🤔 Sin embargo, cualquier falla aquí recae en el usuario. 🙂

¿Puedes darte cuenta de la rejilla de mampostería?

@nikitapilgrim No. Sugeriría usar el componente Masonry de react-virtualized

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

gracias, pero su trabajo solo con react-virtualized?

@nikitapilgrim Sí. 👍
React-virtualized admite un montón de características, que react-window no admite.

El alcance de la ventana de reacción se reduce drásticamente, para centrarse en hacer que el paquete sea más pequeño y más rápido . 😉

Si necesita características de react-virtualized, le sugiero que se quede con eso, ¡sigue siendo una gran biblioteca!

Me encontré con react-window porque estaba buscando una solución a este problema de react-virtualized babel 7 . Estoy usando los componentes react-virtualized Masonry pero ya no puedo después de actualizar babel .

Este no es el lugar para informar problemas con react-virtualized.

De acuerdo @bvaughn. Sin embargo, usted y @babangsund respondieron a @nikitapilgrim arriba que un componente Masonry no se introducirá en react-window y en su lugar usará react-virtualized . Sin embargo, si un usuario está en los últimos [email protected] y [email protected] (como con create-react-app ), react-virtualized no funcionará necesariamente.

Supongo que es información útil para cualquier otra persona que se encuentre en la misma madriguera.
¯ \ _ (ツ) _ / ¯

oye, quiero usar la lista de tamaños dinámicos, ¿dónde puedo descargar la versión 2 o tendré que usar react virtualise?
image

así es como se ve mi lista con una lista de tamaño variable

Este no es un problema de soporte genérico. Mantenga los comentarios sobre el tema.

Se agradecen los comentarios

Estoy usando react-window en un producto similar a trello y aquí hay algunas ideas:

Accesorios de renderizado

Esto parece un buen cambio debido a la simplicidad y para evitar el inconveniente mencionado. Además, la API sería más similar a FlatList de react-native. Recuerdo haber leído la discusión en https://github.com/bvaughn/react-window/issues/85.

Menos componentes
No más soporte de lista horizontal

Voto en contra de la eliminación de horizontal support y VariableSizeList . Como puedes imaginar, estos son los dos principales que utilizo. ¿Es su implementación realmente una carga demasiado pesada de mantener? Si no es así, espero que pueda reconsiderarlos y conservarlos.

No tengo opiniones sólidas relacionadas con los otros cambios. La eliminación de overscanCount me preocupa un poco, pero aún no he enfrentado casos de uso en los que se requiera un valor personalizado, por lo que probablemente esté bien.

¡Hola @bvaughn! ¡Gracias por este paquete! Estoy buscando incorporar la versión 2 en mi proyecto en el trabajo. ¿Tiene un estadio de béisbol sobre cuándo podría ser lanzado?

Gracias por esta biblioteca, y compartir su plan para futuras versiones es muy útil para ayudarnos a mitigar la deuda técnica.

¿Existe una forma "sencilla" de tener WindowScroller comportamiento de react-window reciente y posteriores en la versión 2?

Si no es posible, ¿estaría fuera del perímetro de esta versión 2? ¿O esto podría agregarse más tarde?

Mi contexto es que mi diseño incluye un pie de página, y el uso de un enfoque moderno como DynamicSizeList introduciría una segunda barra de desplazamiento (una para la página y otra para la lista de productos)

Gran paquete. Esperando ansiosamente listas de alturas dinámicas de forma predeterminada, en este momento escribí un montón de lógica personalizada para pasar las alturas de filas renderizadas a la lista principal. Ojalá con esta nueva versión pueda eliminar esa lógica. ¡Gracias por tu trabajo en esto!

@ltkn @mrdanimal

Ya existe una forma de utilizar el desplazador de ventana:
https://github.com/bvaughn/react-window/issues/30#issuecomment -428868071

Cómo hacer Scroll infinito en ambas direcciones, izquierda o derecha !!!

Si tenemos WindowScroller sin depende de react-virtualized , será genial. Debido a que el objetivo detrás de react-window hizo mucho más eficiente y menos código en comparación con react-virtualized Entonces, no quiero usar WindowScroller de react-virtualized . En su lugar, busque un paquete separado como react-virtualized-auto-sizer .

Gracias por adelantado.

@prabusamvel hm ..
¿Cuál es la ventaja de un paquete separado?

He estado jugando con el nuevo DynamicSizeList. ¡Muy genial! Creo que una gran mejora sería incluir 'ttb' y 'btt' (de arriba hacia abajo, de abajo hacia arriba) en el tipo de dirección. Actualmente no existe una forma limpia de implementar una lista que se desplaza hacia arriba, pero se admiten todas las demás direcciones.

@toddmacintyre No puedo encontrar esta versión 2. ¿

@muhammedmagdi npm install react-window@next

Sería genial si la versión 2 pudiera admitir las estructuras DOM requeridas por la especificación aquí: https://www.w3.org/TR/wai-aria-1.1/#grid ya que # 217 sigue siendo un problema para nosotros. Por lo que puedo decir, su propuesta para la versión 2 en este momento no lo hace.

@mjurkowski @bvaughn yarn add react-window@next instala 1.6.0-alpha.1 . Además, al intentar ejecutar el ejemplo de caja de arena de lista dinámica https://react-window-next.now.sh/#/examples/list/dynamic -size arroja Error importing GitHub repository: Could not find package.json

¿Qué tal pasar el index en Grid también, mientras lo hace?

Parte de nuestra aplicación requiere una cuadrícula con encabezados de columna de ancho variable. Lo hemos logrado mediante el uso de una lista de tamaño variable horizontal junto con una cuadrícula y sincronizando el desplazamiento de los dos.

Eliminar listas horizontales nos impedirá crear esa interfaz de usuario (o al menos tendremos que volver a escribirla para usar 2 cuadrículas donde la cuadrícula de encabezado de columna tiene una sola fila.

El siguiente producto se ve increíble. Pero necesito tanto horizontal como vertical, así que para su información, creé el mío: https://www.npmjs.com/package/react-infinite-grid-scroller. Utiliza diseño de cuadrícula, react hooks, IntersectionObserver y requestIdleCallback.

Comentarios bienvenidos.

Tengo la sensación de que soportar elementos adhesivos sería una gran adición a react-window. Es un caso de uso bastante común y sería sencillo de implementar tanto para listas como para cuadrículas.

La API podría verse así:

<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}
/>

Los dos elementos clave para que la adherencia funcione son:

  1. solo desmonte las celdas que estén pegajosas si están fuera de la ventana en el eje no están pegajosas
  2. use position: sticky lugar de absolute , y use margin-x lugar de left y top para el eje que no es pegajoso

El costo de una característica tan excelente parece razonable:

  • La huella es mínima
  • Sin impacto importante en el rendimiento (solo renderizando algunas filas / columnas adicionales)
  • La compatibilidad con el navegador es excelente, y aquellos que no admiten position: sticky solo ven una versión normal

Si cree que este caso de uso es demasiado específico para ser admitido tal como está, un gran compromiso sería admitir solo el punto 1. Ser capaz de especificar si una celda debe renderizarse o no permitiría implementar la adherencia fácilmente.

Estaría encantado de ayudar si es necesario.

no admite la medición y actualización automática de sus tamaños.

Siento que esto es un gran inconveniente. Para casi todas las cuadrículas que he escrito, necesito tener 3 o 4 columnas de ancho fijo (para una etiqueta de estado, algunos metadatos, una llamada a la acción, etc.) y 1 columna de ancho dinámico que ocupa el resto del espacio disponible.

Aprecio que "no es compatible" no significa necesariamente que esto no sea posible con la adición de código y componentes adicionales como Autosizer; sería bueno tener esos casos de uso bien considerados y las soluciones documentadas para aquellos que necesitan un columna dinámica pero no quiero ir a reaccionar-virtualizado por todo el equipaje que trae consigo.

Sería bueno tener esos casos de uso bien considerados y las soluciones documentadas para aquellos que necesitan una columna dinámica.

Totalmente entendido, pero prácticamente hablando, eso requeriría mucho esfuerzo , y esta biblioteca ha sido un trabajo de amor (no un esfuerzo pagado). Desafortunadamente, ni siquiera he tenido tiempo de terminar mis esfuerzos v2 de alcance , y mucho menos algo más agresivo. 😞

Sería bueno tener esos casos de uso bien considerados y las soluciones documentadas para aquellos que necesitan una columna dinámica.

Totalmente entendido, pero prácticamente hablando, eso requeriría mucho esfuerzo , y esta biblioteca ha sido un trabajo de amor (no un esfuerzo pagado). Desafortunadamente, ni siquiera he tenido tiempo de terminar mis esfuerzos _scoped_ down_ v2, y mucho menos algo más agresivo. 😞

Sí. Lo entiendo. Con suerte, ese tipo de esfuerzos pueden ser dirigidos por la comunidad.

Sería bueno, pero en mi experiencia, eso nunca sucede: sonríe:

No he podido usar WindowScroller con DynamicSizedList, probablemente debido a que el renderizado justo a tiempo hace que scrollTo no funcione muy bien. ¿Será esto posible con la nueva versión?

He aceptado el hecho de que no tengo el tiempo ni la energía para terminar este esfuerzo. Si alguien quisiera intervenir y terminar la rama que comencé, agradecería su ayuda. (Consulte también el número 6 para obtener detalles sobre List y Grid deben implementarse para admitir mediciones justo a tiempo).

Hola @bvaughn ,
He creado una discusión en mi bifurcación con algunas notas aleatorias.
Avísame si hay algo que no debería estar en la lista o que no sea correcto. Completaré la lista cuando avance.

Parece algo bueno

¿Fue útil esta página
0 / 5 - 0 calificaciones