React-window: Admite contenido medido justo a tiempo

Creado en 30 may. 2018  ·  132Comentarios  ·  Fuente: bvaughn/react-window

Para evitar agregar costos a la lista existente y los componentes de la cuadrícula, cree una nueva variante (por ejemplo, DynamicSizeList y DynamicSizeGrid ). Esta variante debería medir automáticamente su contenido durante la fase de confirmación.

MVP

La implementación inicial de esto podría funcionar de manera similar a cómo funciona CellMeasurer en react-virtualized:

  1. El contenido se mide solo si no existen mediciones de corriente.
  2. Las mediciones deben restablecerse externamente (imperativamente) si algo cambia.
  3. Las celdas de un índice determinado solo se pueden colocar después de que se hayan medido todas las celdas anteriores a ese índice.

Objetivo

Este componente podría funcionar mejor si elimináramos la tercera restricción anterior, permitiendo el acceso aleatorio (ya sea por índice de elemento o desplazamiento de desplazamiento) sin medir los elementos anteriores. Esto haría que la ventana de reacción sea mucho más eficaz para casos de uso como aplicaciones de chat.

Esto también desbloquearía la capacidad de usar un ResizeObserver (a través de react-medir ) para detectar automáticamente el tamaño del artículo y eliminar la posición y la memoria caché de medidas por completo. Esto eliminaría la necesidad de restablecer imperativamente las mediciones en caché y mejoraría drásticamente la API.

Para que lo anterior sea posible, los componentes de lista / cuadrícula dinámicos necesitarían usar un enfoque dramáticamente diferente para mapear el desplazamiento al índice y viceversa. ( Este comentario sobre el "anclaje de desplazamiento" en react-virtualized tiene algunas imágenes agradables). Esencialmente, tendríamos que hacer algo como esto:

  • Calcule el tamaño total en función del número de artículos multiplicado por estimatedItemSize prop. (No será necesario ajustar este tamaño estimado, ya que el mapeo que se describe a continuación no es difuso).

  • Cuando cambia la posición de desplazamiento, compare el nuevo desplazamiento con el desplazamiento anterior. Si el delta es mayor que algún umbral [por determinar] , establezca el nuevo desplazamiento como el "ancla de desplazamiento". Asigne el desplazamiento a un índice estimado (por ejemplo, divida el desplazamiento por el tamaño total de desplazamiento estimado y multiplíquelo por el número de elementos de la colección). Almacene este índice mapeado como el "índice de anclaje". Por ejemplo, si la lista descrita por la imagen a continuación tuviera 250 elementos, el "índice de anclaje" sería 132.

screen shot 2018-06-10 at 11 58 38 am

  • Cuando cambia la posición de desplazamiento, si el delta es menor que el umbral , elija qué elementos nuevos representar en relación con el índice de anclaje. Coloque estos elementos en relación con los elementos colocados anteriormente. Continuando con el ejemplo anterior, si la lista se desplazó una pequeña cantidad (200 px), entonces se necesitarían agregar 200 px de filas adicionales debajo de los elementos colocados previamente:

screen shot 2018-06-10 at 12 01 01 pm

El enfoque anterior tiene solo una desventaja importante: alinear los elementos correctamente en los límites de la lista. Si se estiman los índices de elementos (como se describe anteriormente), es probable que no se alineen exactamente con el principio o el final del área desplazable.

  • El final podría tenerse en cuenta ajustando el tamaño total estimado a medida que el usuario se desplaza más cerca del final (aunque esto puede hacer que el desplazamiento se sienta inestable).
  • El comienzo de la lista es más difícil de manejar, ya que el primer elemento debe alinearse con el desplazamiento cero y, al mismo tiempo, parece estar conectado de forma contigua con los elementos de algún desplazamiento mayor que cero. Quizás se podría usar otro umbral, una "zona segura", cerca del inicio de la lista (por ejemplo, si el desplazamiento de desplazamiento es menor que algún valor absoluto) que obligaría a la lista a medir todas las celdas hasta ese punto para que se alineen correctamente. El costo de esta medición forzada sería relativamente bajo, ya que solo sería un pequeño número de artículos.
    screen shot 2018-06-10 at 5 04 42 pm

El único caso que todavía no se manejaría correctamente con el enfoque anterior sería un ancla de desplazamiento que se establece fuera de la "zona segura", pero un desplazamiento actual que va dentro de la zona segura (como se muestra a continuación). Si el usuario se desplaza lentamente hacia el principio de la lista, puede resultar difícil alinear la primera celda con cero sin introducir el desplazamiento janky.
screen shot 2018-06-10 at 5 08 26 pm

👋 help wanted

Comentario más útil

No hay "ustedes" en este proyecto. Lo mantiene una sola persona.

Y es un poco desconsiderado dejar comentarios sobre varios temas en el mismo día quejándose de lo mismo. Por supuesto, utilice react-virtualized.

Todos 132 comentarios

Trabajo en progreso para MVP disponible en https://github.com/bvaughn/react-window/compare/master...issues/6

Utilizo esto dentro de mui-downshift y actualmente todavía uso UNSAFE_componentWillReceiveProps , aunque planeo intentar migrar a react-window en un futuro cercano (una vez que la altura del contenido dinámico esté disponible).

¿Es este un mecanismo reutilizable en UITableView en IOS?

@luoboding No entiendo tu pregunta. ¿Podría darnos más detalles?

@bvaughn lo siento, amigo mío, mi inglés no es muy bueno.

Tengo un problema en mi proyecto, tengo miles de opciones en el elemento seleccionado, se vuelve muy lento y se atasca cuando se recarga la página, intenté escribir un componente para mejorarlo, era un desarrollador de IOS, conozco un mecanismo reutilizable en UITableView en IOS, si necesito un elemento de selección de altura de 500px, configuro la altura del elemento de opción a 100px, así que solo necesito crear (Math.floor (500/100)) el número de elemento de opción y la capacidad de la cola (cola de origen de datos mostrada actualmente ), cuando desplazo el elemento de selección hacia arriba o hacia abajo, simplemente presione o aparezca en la cola para volver a renderizarlo.

Quiero importar react-window en mi proyecto, ¿funciona como mencioné?

Lo que está describiendo es cómo funciona la ventana de reacción (y la ventana, o la eliminación de oclusión, en general). Sin embargo, no está realmente relacionado con este problema. Se trata de medir justo a tiempo el contenido de la ventana. En su caso, los objetos tienen una altura fija, por lo que puede usar el componente FixedSizeList : https://react-window.now.sh/#/examples/list/fixed -size

Es bueno ver el anclaje abordado de forma nativa en react-window.

Por cierto, lo siento si elevé demasiado el listón en los diagramas ... 😅

@bvaughn, ¿ cuándo lanzarán esta función? Estoy buscando eso

Publiqué 1.0.0 sin esta funcionalidad porque tengo problemas para encontrar el tiempo (y la energía) para terminar esto ahora mismo. Todavía planeo agregarlo en el futuro. No hay estimación de cuándo.

Parece que la "lista de hierro" de Polymer utiliza una técnica similar a la que propongo aquí: https://github.com/domenic/infinite-list-study-group/blob/master/studies/Polymer-iron-list.md #virtual -list-sizing

esto sería realmente útil para nosotros, en este momento parece que tenemos que mantener CSS sincronizado con la lógica del componente que duplica el cálculo de la altura solo para pasarlo a la lista virtual.

@kevinder, ¿ puede compartir cómo está abordando el contenido medido justo a tiempo? Gracias por adelantado

@carlosagsmendes no estoy seguro de si esto ayudará, pero esto es lo que estoy haciendo cuando uso esto para mostrar el historial de chat:

1.) En el constructor, cree una referencia para la lista y para mi componente ChatHistory :

  constructor(props) {
    super(props);
    this.listRef = createRef();
    this.chatHistoryRef = createRef();
    this.listHeight = 0;
  }

Luego paso las referencias al ChatHistory que es responsable de representar la lista

2.) En componentDidMount del componente principal utilizo ChatHistory ref para obtener la altura del elemento:

componentDidMount() {
    this.listHeight = this.chatHistoryRef.current.offsetHeight;
}

3.) En el componente principal, mantengo una matriz en su estado con los detalles de la historia. Al agregar un nuevo elemento a esa matriz, lo hago así:

  // find out how many pixels in height the text is going to use
  const size = getSize({
    text: displayText,
    className: styles.message,
  });

  let { height } = size;
  height += 20; // adds some spacing in pixels between messages
...rest of items needed for the chat history item..add them all to an array and update state

getSize se basa en https://github.com/schickling/calculate-size pero lo modifiqué para admitir la aceptación de un nombre de clase. Esa clase es la misma que se usa como contenedor para mostrar los mensajes individuales.

Estoy seguro de que hay una mejor manera de lograr esto, pero parece bastante rápido y aún no he encontrado ningún problema.

@osdlge : ¿Alguna posibilidad de que tenga una demostración de esto en cualquier lugar que pueda ver, como Code Sandbox (o similar)?

¡Gracias por compartir! 😄

Empujé algunos trabajos en progreso a un enfoque inicial sobre contenido medido de manera perezosa a una rama llamada problema / 6

También implementé una demostración:
https://react-window-next.now.sh/#/examples/list/dynamic -size

Muy genial.

Todavía estoy tratando de dar sentido a los problemas generales con el desplazamiento infinito mientras reviso la fuente de la rama del problema / 6 y esta discusión. Entonces, la pregunta que sigue a la pregunta puede no tener sentido, pero aquí va, ya que realmente me gustaría entender esto más a fondo:

¿La mención anterior de 'Scroll Anchor' está relacionada con el anclaje de desplazamiento como una técnica como en el artículo vinculado o la especificación de anclaje de desplazamiento CSS ?

Gracias por adelantado

Está relacionado tangencialmente con su primer enlace, pero no con el segundo. Es solo un término que elegí usar para el problema porque tenía sentido para mí, no porque esté relacionado con ninguna otra especificación o propuesta.

También publiqué una versión preliminar de react-window a NPM como "siguiente" (por ejemplo, yarn add react-window@next ).

Puedes jugar con él bifurcando este Code Sandbox:
https://codesandbox.io/s/5x8vlm0o7n

Lo acabo de probar. Intenté 10000 párrafos y traté de saltar hasta el final. Fue espasmódico.
Si entendí correctamente, solo debería haber medido las filas estimadas al final y, por lo tanto, debería haber saltado instantáneamente hasta el final. ¿Es esto correcto?

El 12 de octubre de 2018, a las 12:53, Brian Vaughn [email protected] escribió:

También publiqué una versión preliminar de react-window en NPM como "siguiente" (por ejemplo, yarn add react-window @ next).

Puedes jugar con él bifurcando este Code Sandbox:
https://codesandbox.io/s/5x8vlm0o7n https://codesandbox.io/s/5x8vlm0o7n
-
Estás recibiendo esto porque estás suscrito a este hilo.
Responda a este correo electrónico directamente, véalo en GitHub https://github.com/bvaughn/react-window/issues/6#issuecomment-429271555 , o silencie el hilo https://github.com/notifications/unsubscribe-auth/ AOf2h7RmSEyGmyrEdMY6GgyZFjCKlDDFks5ukGafgaJpZM4UTb3P .

No, la rama inicial que empujé no implementa el algoritmo
descrito en este número. Se necesita un enfoque más ingenuo que requiere
medir el contenido anterior antes de procesar el contenido posterior.

¡Perdón por la confusion!

El viernes 12 de octubre de 2018 a las 6:34 p.m. akraines [email protected] escribió:

Lo acabo de probar. Intenté 10000 párrafos y traté de saltar al
final. Fue espasmódico.
Si entendí bien, solo debería haber medido las filas estimadas
estar al final y, por lo tanto, debería haber saltado instantáneamente al
final. ¿Es esto correcto?

El 12 de octubre de 2018, a las 12:53, Brian Vaughn [email protected] escribió:

También publiqué una versión preliminar de react-window a NPM como
"siguiente" (por ejemplo, hilo añadir ventana de reacción @ siguiente).

Puedes jugar con él bifurcando este Code Sandbox:
https://codesandbox.io/s/5x8vlm0o7n < https://codesandbox.io/s/5x8vlm0o7n

-
Estás recibiendo esto porque estás suscrito a este hilo.
Responda a este correo electrónico directamente, véalo en GitHub <
https://github.com/bvaughn/react-window/issues/6#issuecomment-429271555>,
o silenciar el hilo <
https://github.com/notifications/unsubscribe-auth/AOf2h7RmSEyGmyrEdMY6GgyZFjCKlDDFks5ukGafgaJpZM4UTb3P
.

-
Recibes esto porque te mencionaron.
Responda a este correo electrónico directamente, véalo en GitHub
https://github.com/bvaughn/react-window/issues/6#issuecomment-429282228 ,
o silenciar el hilo
https://github.com/notifications/unsubscribe-auth/AABznR5R1N0ErukleIfvaLQORF_NECgRks5ukHBHgaJpZM4UTb3P
.

Oye,
Quería preguntar si hay una estimación para un lanzamiento oficial.

Mi equipo usa react-virtualized para un nuevo proyecto que comenzamos, sin embargo, necesitamos la funcionalidad de desplazarse hacia arriba y saltar al índice de fila específico (ya que puede asumir que nuestras filas tienen contenido dinámico, con imágenes y otro contenido cambiante).

¿Recomendaría migrar a react-window en su versión alfa? ¿O deberíamos esperar un lanzamiento oficial?

Además, si hay alguna forma en que pueda contribuir a completar esta función, me encantaría ayudar 😄

Desafortunadamente, no puedo comprometerme con una línea de tiempo de lanzamiento en este momento porque no he hecho muchas pruebas y no sé qué tipo de problemas me encontraré cuando lo haga (o cuánto tiempo tomará solucionarlo ellos).

Si desea contribuir, una forma sería probar la versión alfa y hacerme saber qué tan bien funciona, y si encuentra algún error.

Probablemente me centraré más en esto pronto, pero no puedo decir cuándo. Especialmente durante la próxima semana o dos, estoy distraído con React conf y preparando la versión 16.6.

@bvaughn gran trabajo 👏 Finalmente, tengo algo de tiempo para jugar. 🕹

Parece que necesitamos algunos ajustes al ocultar la lista con display: none Por ejemplo, tiene una página con dos pestañas y desea cambiar entre ellas sin perder su estado actual (posición de desplazamiento, etc.), en mi humilde opinión, no es un caso de uso raro .

Sandbox de código simple que presenta el problema:
https://codesandbox.io/s/p7vq18wmjq

Está sucediendo porque cuando activamos display none, todos los niños tendrán offsetHeight === 0
resize observa kiks in y actualizó los nuevos valores. react-window no debería preocuparse por estas situaciones si la persona que llama decidió ocultarlo, básico debería manejarlo bloqueando handleNewMeasurements

si esta linea
https://github.com/bvaughn/react-window/blob/issues/6/src/DynamicSizeList.js#L443
cambiaría a

handleNewMeasurements: instance._handleNewMeasurements

entonces podemos anular la lógica predeterminada

let _handleNewMeasurements

<DynamicSizeList  
  ref={current => {
    if (current) {
      _handleNewMeasurements = current._handleNewMeasurements
      current._handleNewMeasurements = (...args) => {
        if (!isHidden) {
          return _handleNewMeasurements(...args)
        }
      }
    }
  }}
  {...otherProps}

Envié una actualización a esta rama (y publiqué una nueva etiqueta @next en NPM) que corrige el error de desplazamiento suave de Firefox usando margin-top para tener en cuenta los elementos redimensionados mientras el desplazamiento está en curso. Es más complicado de lo que me gustaría, pero no conozco una mejor manera de manejar esto en este momento. (También necesito hacer algunas pruebas más de este enfoque, porque creo que podría tener algunos aspectos ásperos en casos extremos).

Agradezco los comentarios anteriores, @piecyk. Todavía no he tenido tiempo de investigarlo. (Esto todavía es solo un proyecto paralelo para mí en este momento).

Parece que puedo eliminar el truco de margen a favor de scrollBy para Firefox al menos . Sin embargo, primero debe probar IE y Edge. Pueden tener sus propios desafíos.

@bvaughn , lo sé, trabajo increíble 👏 ¡No sé cómo encuentras el tiempo! 🥇¡Muchas felicitaciones!

Pero volvamos al problema cuando la lista está en algún elemento DOM que está oculto sin mostrar ninguna, básico, necesitamos verificar si el contenedor tiene alto, ancho si no, no queremos comenzar a renderizar (actual, intentará renderizar toda la lista) Intentaré arreglarlo mañana (tener algo escondido)

Sí. Entiendo el meollo del problema que estás describiendo. Sin embargo, no me gusta la idea de piratearlo anulando / parcheando más métodos de instancia, así que me gustaría pensarlo un poco más primero.

¿Parece que el paquete @next está roto?

https://codesandbox.io/s/5x8vlm0o7n

No sé si ese es el lugar adecuado para dejar una pregunta, así que discúlpeme si me equivoco. Entonces, en resumen:

  • He usado DynamicSizeList junto con AutoResizer y, en general, funciona muy bien. ¡Prestigio!
  • Se me ha pedido que presente Filas cuyo contenido pueda expandirse (agregando un div adicional con información complementaria) y retractarse.
  • También agregué (a través de redux) un accesorio en estas filas que escucha las acciones globales de expansión / retracción.
  • Comienzan las cosas divertidas. ¡Hago clic en expandir / retraer y todo se ve genial!
  • Si me desplazo un poco y luego amplío / retraigo todas las filas, el número de filas retraídas es el mismo que el de las filas expandidas. Si vuelvo a expandir la retracción, el número se reduce a la mitad y así sucesivamente.
    (es decir, 30 filas retraídas -> 10 expandidas -> haga clic en retraer -> 10 filas retraídas -> haga clic en expandir -> 3 filas expandidas -> haga clic en retraer -> 3 filas retraídas).

Intenté recargar itemData proporcionando un objeto diferente pero el mismo con el truco JSON.parse (JSON.stringify (data)). Sin suerte :-(

Sospecho un error de cálculo de la altura. ¿Alguna idea para superar este problema?

¿Podría compartir un ejemplo de codesandbox? Necesito hacer algo similar, así que tal vez podamos ayudarnos unos a otros.

@vtripolitakis Acabo de encontrar un ejemplo con filas expandibles . Aquí está el enlace a la discusión.

@carlosagsmendes gracias por esto, pero mi caso de estudio es un poco diferente ya que uso el DynamicSizeList :-(

Entonces encontré el motivo del problema:
state.scrollOffset estaba tomando valores negativos.

en src/DynamicSizeList.js necesitamos agregar el siguiente código en la línea 299

if (sizeDeltaForStateUpdate < 0) {
          sizeDeltaForStateUpdate = 0;
        }

Hm ... No esperaría que esa solución fuera la correcta, de un vistazo. Un delta de tamaño podría ser legítimamente negativo, ¿no?

¿Quizás deberíamos tener un guardia ( Math.max(0, prevState.scrollOffset + sizeDeltaForStateUpdate) ) alrededor de donde se actualiza el valor state.scrollOffset ?

Hola, mientras depuraba mi caso, sizeDeltaTotal tomó valores negativos y, en consecuencia, hice sizeDeltaForStateUpdate negativo, lo que arrojó un state.scrollOffset negativo después de la actualización del estado.

Esto sucedió cuando expandí y retiré elementos y luego me desplacé hacia la parte superior con scrollOffset 0 y la dirección backwards . Luego, si me expando y retracto un par de veces, obtengo los negativos.
Sí, tu sugerencia debería ser igualmente buena. ~ Probándolo ahora mismo. ~ Funciona correctamente.

@marcneander prueba la versión 1.4.0-alpha.1

Con respecto a ignorar los eventos de cambio de tamaño cuando la lista está oculta, tal vez algo como esto https://github.com/piecyk/react-window/commit/acfd88822156611cfd38872acdafbbefd2d0f78f
@bvaughn ¿qué piensas?

Estoy tratando de agregar desplazamiento automático en una aplicación de estilo chatbox y me encuentro con este problema: DynamicSizeList does not support scrolling to items that have not yet measured. scrollToItem() was called with index 111 but the last measured item was 110.

Estoy intentando llamar a scrollToItem(items.length-1) en componentDidUpdate

¿Es este comportamiento previsto?

Sí, tal vez algo así podría funcionar @piecyk 👍

¿Es este comportamiento previsto?

No suena así @xaviergmail , no. Quizás un error.

Hola @bvaughn, no pretendo descarrilar este problema, pero quería intervenir para decir que hay una implementación ordenada de

LinearLayoutVector es una matriz dispersa para mapear entre índices de elementos y posiciones de píxeles en una sola dimensión. Las tres operaciones básicas son:

interface LinearLayoutVector {
   start: (index) => position;
     end: (index) => position;
  indexOf: (position) => index;
}

Internamente, asigna cubos en potencias de 2 para almacenar posiciones de elementos (la potencia específica se puede ajustar para adaptarse mejor a tamaños de elementos más grandes o más pequeños). Esto permite búsquedas de O (1) index -> position tiempo constante y un escaneo de bloque lineal eficiente para búsquedas de position -> index . Admite relleno, espacios, tamaños predeterminados e inserción, eliminación y actualizaciones de acceso aleatorio.

Lo porté a JS hace unos 6 años cuando estaba haciendo muchas interfaces de usuario virtualizadas para dispositivos móviles. Podría usar una actualización de ES6 para mejorar la legibilidad, y probablemente podría obtener más velocidad al cambiar a matrices escritas, pero la lógica básica es sólida.

Envié un borrador de PR para react-virtualized hace unas semanas que cambió los componentes internos de CellSizeAndPositionManager con el LLV y resolvió algunas cosas de invalidación de rendimiento / caché. Si no está, me complacerá enviar un PR similar a react-window en las próximas semanas.

Hola @trxcllnt 👋

Si está interesado en compartir un PR, me complacerá echarle un vistazo. Querría hacerlo contra la rama issues/6 (WIP PR # 102).

De un vistazo, linear-layout-vector no parece que tenga ninguna prueba o que se esté usando demasiado, por lo que tendría un poco de desgana inicial, pero aún estaría dispuesto a echar un vistazo. También me gustaría ver cuánto peso agrega a un paquete después de ser uglified + minified, pero no esperaría que agregue demasiado. 😄

@bvaughn sin sudar, lo entiendo totalmente. Fue algo que hice hace años durante el IIRC navideño. Lo limpiaré y me aseguraré de que aterrice con un conjunto de pruebas completo. Tampoco se preocupe por incurrir en una dependencia adicional. Es una clase tan pequeña que estoy feliz de contribuir directamente.

Después de comentar, recordé que tenía la demostración para la que hice el puerto: https://github.com/trxcllnt/virt-list. Acceda a ese sitio de páginas de GH y arroje la lista de películas de izquierda a derecha (esto estaba relacionado con algunas discusiones sobre el rendimiento de renderizado que estábamos teniendo en el equipo de iOS en Netflix).

@bvaughn ¡ Gracias por todo el trabajo realizado en la rama de
Actualmente estoy probando ^1.6.0-alpha.1 y planeo enviarlo a producción con esa versión.

Pensé en publicar lo que tenía que hacer para trabajar con el nuevo DynamicSizeList para cualquier otra persona que esté viendo este problema y usando la última versión de la sucursal.

Seguir los documentos vinculados anteriormente y los generados a partir de la rama issues / 6 conducirá a

Warning: Function components cannot be given refs. Attempts to access this ref will fail. Did you mean to use React.forwardRef()?

así que la solución fue imitar lo que haces en las pruebas y ...

import { DynamicSizeList as List } from 'react-window';
import AutoSizer from 'react-virtualized-auto-sizer';

// in constructor(props) for handling scrolling
this.listRef = React.createRef();

// in render()
const allItems = [...];
const Renderer = ({ forwardedRef, style, index, ...rest }) => (
  <div ref={forwardedRef} style={style}>
    <MyCoolComponent index={index} otherProps={otherPropsBasedOnAllItems} />
  </div>
);

const RefForwarder = React.forwardRef((props, ref) => (
  <Renderer forwardedRef={ref} {...props} />
));

return <div style={{ display: 'flex', flexDirection: 'column', height: '100%' }}>
  <div style={{ flexGrow: 0, flexShrink: 0, width: '100%', position: 'sticky', top: 0, zIndex: zIndexHideLayers }}>
    <MyCoolComponentThatControlsScrolling listRef={this.listRef} />
  </div>
  <div style={{ flex: 1, width: '100%' }}>
    <AutoSizer>
      {({ height, width }) => (
        <List ref={this.listRef} itemCount={allItems.length} width={width} height={height}>
          {RefForwarder}
        </List>
      )}
    </AutoSizer>
  </div>
</div>;

Mi ejemplo probablemente incluye más de lo que desearía en esa página de documentos, pero con suerte hará que la actualización del documento sea más fácil para usted.

¿Comentarios sobre la versión actual de la sucursal?
💯 funciona bien
🎉 gracias de nuevo por todo el trabajo!

edit: DynamicSizeList hace que esta biblioteca sea tan fácil de usar ahora.

¡Gracias por compartir los detalles! Cuando tenga algo de ancho de banda para recuperar este problema, profundizaré en ellos.

Creo que este enfoque puede utilizarse junto con la propuesta original en este número.

En lugar de usar el tamaño anterior del artículo, podríamos usar los tamaños estimados y refinar con los tamaños reales a medida que alguien se desplaza. (No creo que exista una distinción importante entre "tamaño medido previamente" y "tamaño estimado", excepto por el hecho de que es probable que el tamaño medido anteriormente sea más preciso. Aún así, esta podría ser una compensación aceptable, ya que permitiría que saltemos a lugares arbitrarios en los datos sin representar las cosas que vinieron antes, y nos liberaría de tener que mantener un caché de tamaño de elemento).

Creo que esto podría simplificar significativamente el problema de anclaje de desplazamiento. Podríamos simplemente hacer el salto inicial (como se describe) y luego pretender que todo "antes" (arriba o izquierda) tenía exactamente el tamaño estimado. Luego, a medida que nos desplazamos, refinamos.

¿Quizás podría funcionar?

@bvaughn ¿Esto solucionará el problema que abordó @xaviergmail , con el desplazamiento inicial hacia el "final" como un chat? Creé un código y una caja de un ejemplo de que no funciona. Si no es así, ¿existen soluciones alternativas?

https://codesandbox.io/s/vr648ywy3

Mantengamos los comentarios sobre este problema centrados en la discusión de la API, no en la resolución de problemas.

Sugiero Stack Overflow para hacer preguntas.

¿Es posible exponer resetAfterIndex en esta API? Agrego, edito y elimino de mi DynamicSizeList y, al menos de lo que puedo recopilar, este sería el método para llamar para arreglar alturas, ¿no?

@bvaughn estuvo jugando durante el fin de semana con la idea de colocar los elementos con un índice de anclaje y desplazar la lista para alinear lo que ve el usuario ... Primeras impresiones de que podría funcionar 😅 Para simplificar, la lista se representa sin ningún elemento de sobreexploración, también nosotros Necesito cambiar cómo funciona el caché (en este wip siempre se borra) ... ¿Qué piensas?

implementación de poc https://github.com/piecyk/react-window/pull/2/files
aquí está el sandbox de código que ejecuta la compilación de la rama
https://codesandbox.io/s/4x1q1n6nn9

uh-oh, firefox no puede seguir el ritmo de la renderización cuando el desplazamiento rápido como lo hace Chrome con este enfoque 🤷‍♂️

Estoy tratando de agregar desplazamiento automático en una aplicación de estilo chatbox y me encuentro con este problema: DynamicSizeList does not support scrolling to items that have not yet measured. scrollToItem() was called with index 111 but the last measured item was 110.

Estoy intentando llamar a scrollToItem(items.length-1) en componentDidUpdate

¿Es este comportamiento previsto?

Un poco tarde, pero estoy tratando de resolver ese problema con este gancho de reacción.

No es la mejor solución, pero todavía estoy trabajando en ella. ¿Quizás podamos trabajar para hacerlo más genérico (y simple) y crear un paquete?

Gif para mostrar cómo está funcionando esto en este momento:
https://cl.ly/87ca5ac94deb

¿Quizás podamos abrir un nuevo problema para hablar sobre una solución para este comportamiento similar al chat?

uh-oh, Firefox no puede seguir el ritmo de la renderización cuando el desplazamiento rápido como lo hace Chrome con este enfoque

Parece que funciona en la versión 68 de Firefox Nightly.

@bvaughn Estoy usando DynamicSizeList con los componentes InfiniteLoader y Autosizer para intentar crear un feed. Me gusta lo que he visto hasta ahora, sigue así :)

En términos de API y comportamiento:

  1. ¿Podemos obtener el objeto de datos como segundo argumento en la devolución de llamada itemKey, tal como está en FixedSizeList?

  2. ¿Podemos restablecer la altura del contenedor interno cuando el objeto de datos se filtra / modifica?

He estado usando DynamicSizeList de 1.6.0-alpha.1 con InfiniteLoader por un tiempo y ha funcionado muy bien. ¡Gracias por la fantástica función!

Sin embargo, ahora tengo el requisito de usar scrollToItem() . Similar a un comentario anterior, pero distinto porque todavía no se mide nada en absoluto, obtengo:

DynamicSizeList does not support scrolling to items that yave not yet measured. scrollToItem() was called with index 9 but the last measured item was -1.

No parece estar relacionado con el tiempo, ya que intenté llamarlo después de un largo setTimeout . Entonces, ¿puedo forzar una medición? ¿O hay alguna solución alternativa?

EDITAR : No importa, initialScrollOffset hizo lo que necesitaba.

¿Por qué utilizar findDOMNode?

¿Existen definiciones de tipo para la rama @next ?

@WillSquire no, no lo hacen. Tampoco estoy seguro de si es posible publicarlos en la etiqueta @next en DefinitelyTyped (podría estar equivocado). Además, creo que sería mejor esperar hasta que esta rama finalmente se fusione y se publique una nueva versión, ya que la API aún podría cambiar.

@bvaughn He estado dispuesto a usar esto en devhub , pero antes de invertir en integrarlo, ¿crees que ya está en buena forma o todavía tiene algunos problemas de bloqueo?

@brunolemos Creo que mi lista de

¡mantenme informado!

~ Traté de usarlo pero no lo he logrado hasta ahora. ~

Lo tengo funcionando, pero el rendimiento no es bueno. Tal vez los renders de mis artículos sean costosos u otra cosa.

https://github.com/devhubapp/devhub/pull/152

Parece que algo se puede haber roto en la última versión al usar AutoSizer con una altura de contenedor del 100%

Editar: pude encontrar una solución usando 100vh y calc ()

algo puede haberse roto

Demasiado vago para ser procesable. ¿Compartir una reproducción junto con el comportamiento esperado?

Estoy usando DynamicSizeList de 1.6.0-alpha.1 con diferentes filtros y algunas vistas de tarjeta complejas. Pero necesitamos envolver con la altura y el ancho. Está funcionando bien para mí.

Gracias chicos

Hola, estoy probando DynamicSizeList , pero todos mis elementos se muestran uno encima del otro. Paso el atributo de estilo al elemento renderizado, pero si registro style , veo que height no está definido para cada elemento, top y left son siempre 0 .
¿Qué me perdí aquí :-)?

@ graphee-gabriel te pierdes un ejemplo de reproducción.

La altura no se especifica intencionalmente inicialmente, para permitir que los elementos se representen con su tamaño natural ...

Ok, entiendo la lógica, entonces esta no es la razón por la que los elementos se muestran uno encima del otro.
Proporcionaré tantos datos como pueda, pensé que tal vez cometí un error común o me perdí un paso obvio que conduce a este problema (como no transmitir el objeto de estilo).

Screen Shot 2019-07-07 at 18 08 53

import React from 'react'
import { DynamicSizeList as List } from 'react-window'

import Layout from '../Layout'
import Text from '../Text'
import withScreenDimensions from '../withScreenDimensions'

class ListView extends React.Component {
  state = {
    availableHeight: 0
  }

  componentDidMount() {
    const checkForHeightChange = () => {
      if (this.containerDiv) {
        const { offsetHeight } = this.containerDiv
        if (this.offsetHeight !== offsetHeight) {
          this.offsetHeight = offsetHeight
          this.setState({ availableHeight: offsetHeight })
        }
      }
    }
    checkForHeightChange()
    this.intervalId = setInterval(checkForHeightChange, 10)
  }

  componentWillUnmount() {
    clearInterval(this.intervalId)
  }

  render() {
    const {
      data,
      renderItem,
      emptyText,
      dimensions,
    } = this.props
    const { width } = dimensions
    const { availableHeight } = this.state
    return (
      <Layout
        centerVertical
        style={{
          height: '100%',
        }}>
        {data && data.length > 0 ? (
          <div
            style={{
              display: 'flex',
              flex: 1,
              height: '100%',
              backgroundColor: 'red',
              alignItems: 'stretch',
              justifyContent: 'stretch',
            }}
            ref={ref => this.containerDiv = ref}
          >
            <List
              height={availableHeight}
              itemCount={data.length}
              width={width > 800 ? 800 : width}
            >
              {({ index, style }) => {
                console.log('style', style)
                return (
                  <div style={style}>
                    {renderItem({
                      item: data[index], index
                    })}
                  </div>
                )
              }}
            </List>
          </div>
        ) : (
            <Text bold center padding accent>{emptyText}</Text>
          )}
      </Layout>
    )
  }
}


export default withScreenDimensions(ListView)

¿Compartir una zona de pruebas de código donde pueda ver esto?

Sugeriría _no_ usar una función en línea para el renderizador de su elemento porque causa remontes innecesarios debido al hecho de que cambia cada vez que se renderiza el padre. (Esta es la razón por la que todos los ejemplos evitan las funciones en línea).

@ graphee-gabriel También he tenido esto, los documentos no lo mencionan, pero debe hacer que su componente de fila admita la recepción de una referencia:

Row = React.forwardRef(
      (row, ref) => (
        <div ref={ref} style={row.style}>
          {renderItem({
            item: data[row.index],
            index: row.index,
          })}
        </div>
      ),
    )

Hola, aquí tienes:

https://codesandbox.io/s/sweet-sea-irxl8?fontsize=14

Sí, de hecho, para las funciones en línea, es un código realmente antiguo que intenté migrar a react-window, y no me tomé el tiempo para mejorarlo aquí también.
Gracias por tus comentarios. Déjame saber qué encuentras en esta caja de arena.

Annnnnd debería haber revisado el mensaje @brunolemos antes de hacer ese sandbox jeje.
Este era el paso que faltaba y solucionó mi problema, ¡gracias!

Surgió otro problema, actualicé la caja de arena para que pueda reproducir @bvaughn
Encuéntrelo aquí: https://codesandbox.io/s/sweet-sea-irxl8

Ahora la lista funciona bien, pero extrañamente parece crecer con el contenido y nunca más se reduce.

Significado:

  1. Si muestro 6 elementos, desplácese hasta el final, todo está bien.
  2. Cambie el contenido para mostrar 20 elementos, desplácese hasta el final, todo bien.
  3. Vuelva a cambiar el contenido a 6 elementos, desplácese hasta el último elemento, pero puedo continuar desplazándome por el espacio en blanco que parece quedar del contenido anterior (el conjunto de datos de 20 elementos).

Surgió otro problema, actualicé la caja de arena para que pueda reproducir @bvaughn
Encuéntrelo aquí: https://codesandbox.io/s/sweet-sea-irxl8

Ahora la lista funciona bien, pero extrañamente parece crecer con el contenido y nunca más se reduce.

Significado:

  1. Si muestro 6 elementos, desplácese hasta el final, todo está bien.
  2. Cambie el contenido para mostrar 20 elementos, desplácese hasta el final, todo bien.
  3. Vuelva a cambiar el contenido a 6 elementos, desplácese hasta el último elemento, pero puedo continuar desplazándome por el espacio en blanco que parece quedar del contenido anterior (el conjunto de datos de 20 elementos).

Tengo el mismo problema

Esto es exactamente lo que necesitaba.
Acabo de probar DynamicSizeList de 1.6.0-alpha.1 en combinación con react-virtualized-auto-sizer y react-window-infinite-loader con muy buenos resultados.
¿En algo en lo que pueda ayudar para que esto avance?

Hola @bvaughn , ¿tuviste tiempo para revisar el codesandbox de https://github.com/bvaughn/react-window/issues/6#issuecomment -509213284?

Hola, estoy usando DynamicSizeList para mi aplicación de chat.
Gracias por la fantástica función.

Sin embargo, tengo problemas de bajo rendimiento y mucho procesamiento de scripts.
Al desplazarse, la CPU siempre aumenta y, a menudo, alcanza el 100%.
¿Tiene alguna idea de soluciones?

import { useChatList } from '../../../hooks/chat/useChatList';
import LoadingSpinner from '../../../utils/LoadingSpinner';

import dynamic from 'next/dynamic';
import * as React from 'react';
import AutoSizer from 'react-virtualized-auto-sizer';
// @ts-ignore
import { DynamicSizeList as List } from 'react-window';
import { Message } from 'src/app/typings';

const { useRef, useCallback } = React;

const RowItem = React.memo(
  ({ forwardedRef, style, index, data }: any) => {
    const item = data[index] as Message;
    if (item) {
      return (
        <div id={item.messageId} ref={forwardedRef} style={style}>
          {item.text && item.text.plainText}
        </div>
      );
    }
    return null;
  },
  (prevProps, newProps) => {
    const { index, data } = prevProps;
    const { index: newIndex, data: newData } = newProps;
    let isMemo = true;
    isMemo = isMemo && index === newIndex;
    isMemo = isMemo && data.length === newData.length;
    return isMemo;
  }
);

function ChatList() {
  const listRef = useRef<HTMLInputElement>();

  const { formatMessages: messages, isLoadingMessages } = useChatList();

  const keyCreator = useCallback((index: number) => `ChatList/RowItem/${messages[index].messageId}`, [messages]);

  if (isLoadingMessages && (!messages || messages.length <= 0)) {
    return <LoadingSpinner />;
  }
  return (
    <div style={{ flex: 1, height: '100%', width: '100%' }}>
      <AutoSizer>
        {({ height, width }) => (
          <List
            ref={(lref: HTMLInputElement) => {
              if (lref !== null) {
                listRef.current = lref;
              }
            }}
            itemCount={messages.length}
            itemData={messages}
            itemKey={keyCreator}
            height={height}
            width={width}
            overscanCount={10}
          >
            {React.forwardRef((props, ref) => (
              <RowItem forwardedRef={ref} {...props} />
            ))}
          </List>
        )}
      </AutoSizer>
    </div>
  );
}

export default ChatList;

スクリーンショット 2019-07-14 11 49 54

Hola @bvaughn , ¡buen trabajo!
¿Cuál es la forma correcta de volver a calcular las alturas de los elementos al cambiar el tamaño del lugar de trabajo? Con la ayuda de los comentarios anteriores, hago una demostración https://codesandbox.io/s/angry-hill-tcy2m
Cuando el ancho del lugar de trabajo cambia con el mouse, necesito volver a calcular la altura de todos los elementos (y es posible que esté borrando la memoria caché de altura interna del componente VariableSizeList) ...

¿Hay alguna solución ahora para la lista dinámica? Acabo de pasar 4 horas tratando de que funcione, eh
después de leer todos los comentarios he terminado 😠
Si tienen alguna solución que funcione, por favor proporcionenme

No hay "ustedes" en este proyecto. Lo mantiene una sola persona.

Y es un poco desconsiderado dejar comentarios sobre varios temas en el mismo día quejándose de lo mismo. Por supuesto, utilice react-virtualized.

Lo siento mucho por dejar un comentario como este, Brian. Encontré este problema más tarde y luego leí todos los comentarios y pensé que otros te estaban ayudando al menos

@ShivamJoker Casi lo hago funcionar, lo único que queda para que funcione perfectamente es la altura total que sigue creciendo pero nunca se encoge después de cambiar el contenido a menos elementos. Si esto se resuelve, en mi caso de uso, parecería funcionar perfectamente.

@bvaughn, ¿tendrías tiempo de consultar el ejemplo en la caja de arena de https://github.com/bvaughn/react-window/issues/6#issuecomment -509213284?

=> https://codesandbox.io/s/sweet-sea-irxl8

Comienza con la lista más corta, por lo tanto:

  • desplácese hacia abajo hasta el final de la lista
  • desplácese hacia arriba y haga clic en Show Long List
  • desplácese hacia abajo hasta el final
  • desplácese hacia arriba y haga clic en Show Short List
  • Finalmente, desplácese hacia abajo una última vez para ver que la lista corta ahora está seguida de muchos espacios en blanco.

¡Gracias!

@ShivamJoker Casi lo hago funcionar, lo único que queda para que funcione perfectamente es la altura total que sigue creciendo pero nunca se encoge después de cambiar el contenido a menos elementos. Si esto se resuelve, en mi caso de uso, parecería funcionar perfectamente.

@bvaughn, ¿tendrías tiempo de comprobar el ejemplo en la caja de arena del n . ° 6 (comentario) ?

=> https://codesandbox.io/s/sweet-sea-irxl8

Comienza con la lista más corta, por lo tanto:

  • desplácese hacia abajo hasta el final de la lista
  • desplácese hacia arriba y haga clic en Show Long List
  • desplácese hacia abajo hasta el final
  • desplácese hacia arriba y haga clic en Show Short List
  • Finalmente, desplácese hacia abajo una última vez para ver que la lista corta ahora está seguida de muchos espacios en blanco.

¡Gracias!

Sí, básicamente el contenedor interno debería restablecer su altura al filtrar / cambiar los datos.

@ShivamJoker Casi lo hago funcionar, lo único que queda para que funcione perfectamente es la altura total que sigue creciendo pero nunca se encoge después de cambiar el contenido a menos elementos. Si esto se resuelve, en mi caso de uso, parecería funcionar perfectamente.

@bvaughn, ¿tendrías tiempo de comprobar el ejemplo en la caja de arena del n . ° 6 (comentario) ?

=> https://codesandbox.io/s/sweet-sea-irxl8

Comienza con la lista más corta, por lo tanto:

  • desplácese hacia abajo hasta el final de la lista
  • desplácese hacia arriba y haga clic en Show Long List
  • desplácese hacia abajo hasta el final
  • desplácese hacia arriba y haga clic en Show Short List
  • Finalmente, desplácese hacia abajo una última vez para ver que la lista corta ahora está seguida de muchos espacios en blanco.

¡Gracias!

gracias, he implementado lo mismo con la esperanza de que funcione bien para otros usuarios también
y sí, también vi que el problema de la altura con el desplazamiento

@ graphee-gabriel, pero también tengo un problema más que la barra de mi aplicación solía esconderse en el desplazamiento hacia abajo, lo que no está sucediendo ahora, ¿cuál puede ser la solución?
image

Buenos días. Usé DinamycSizeList en mi proyecto de demostración. Todo estaba bien, pero después de un tiempo noté que el componente de lista comenzaba a funcionar incorrectamente. Al principio pensé que era una biblioteca de la que depende react-window. Pero mirando tu demo
https://react-window-next.now.sh/#/examples/list/dynamic -size
notó el mismo resultado, aunque en el pasado también funcionó perfectamente. ¿Podría sugerir la causa de estos errores?

@simeonoff

Sí, básicamente el contenedor interno debería restablecer su altura al filtrar / cambiar los datos.

¿Cómo debería hacerlo? Intenté poner una altura de estado pero no parece funcionar
alguna solución ?

@simeonoff

Sí, básicamente el contenedor interno debería restablecer su altura al filtrar / cambiar los datos.

¿Cómo debería hacerlo? Intenté poner una altura de estado pero no parece funcionar
alguna solución ?

Debe ser implementado internamente por la biblioteca.

@ShivamJoker Casi lo hago funcionar, lo único que queda para que funcione perfectamente es la altura total que sigue creciendo pero nunca se encoge después de cambiar el contenido a menos elementos. Si esto se resuelve, en mi caso de uso, parecería funcionar perfectamente.

@bvaughn, ¿tendrías tiempo de comprobar el ejemplo en la caja de arena del n . ° 6 (comentario) ?

=> https://codesandbox.io/s/sweet-sea-irxl8

Comienza con la lista más corta, por lo tanto:

  • desplácese hacia abajo hasta el final de la lista
  • desplácese hacia arriba y haga clic en Show Long List
  • desplácese hacia abajo hasta el final
  • desplácese hacia arriba y haga clic en Show Short List
  • Finalmente, desplácese hacia abajo una última vez para ver que la lista corta ahora está seguida de muchos espacios en blanco.

¡Gracias!

Puede configurar la clave para evitar espacios en blanco.
https://codesandbox.io/s/blissful-voice-mzjsc

Hola @bvaughn, ¡gracias por este increíble proyecto!

Por necesidad, he pasado bastante tiempo en el código de DynamicLists tratando de descubrir cómo desplazarme a cualquier lugar sin limitaciones y cómo desplazarme a cualquier elemento, medido y no.

Logré hacerlo aquí https://github.com/bvaughn/react-window/compare/issues/6...Sauco82 : issues / 6 deshaciéndome de lastMeasuredIndex y comprobando por artículo en su lugar con itemIsMeasured , que obviamente requiere muchos otros cambios.

Nunca he participado en un proyecto de código abierto ni he usado Flow, por lo que no estoy muy seguro de si es útil o vale la pena incluirlo, ni si debería probar directamente un PR o discutirlo aquí.

Estoy feliz de ayudar y modificar, así que si necesita algo, hágamelo saber.

Oye, aquí hay una solución mucho más simple (no es necesario agregar elementos fantasmas al DOM para calcular su tamaño):
Códigos y caja

Oye, aquí hay una solución mucho más simple (no es necesario agregar elementos fantasmas al DOM para calcular su tamaño):
Códigos y caja

¡Impresionante! Esto funciona para mi. Buen trabajo.

@Kashkovsky calculó el tamaño si se actualizaba
y itemSize llamar una vez

@ userbq201 @Kashkovsky ¡ gran solución! De alguna manera, en mi caso, no funcionó de inmediato, tuve que modificar el código de ChatHistory.js así:

    const listRef = useRef(); // added
    const sizeMap = useRef({});
    const setSize = useCallback((index, size) => {
        sizeMap.current = {...sizeMap.current, [index]: size};
        listRef.current.resetAfterIndex(index); // added
    }, []);
    const getSize = useCallback(index => sizeMap.current[index] || 60, []);
    // ...
    <List ref={listRef}

De lo contrario, todos los elementos se representan con la misma altura predeterminada. En su caso, funciona como está, no puedo explicar por qué hay una diferencia ... tal vez @bvaughn pueda.

@bvaughn ¿y si tenemos que habilitar un comportamiento similar para SSR? alguna pista para ese lado?

@bvaughn ¿Soy yo o tu demo no funciona?

¡Buena implementación @Kashkovsky @ kirill-konshin y @ userbq201 !

¿Cómo abordaría el uso de la memorización con esta solución?

Intenté envolver ChatMessage en un memo con areEqual , pero React aún vuelve a renderizar cada objeto cada vez que se agrega un mensaje a la lista.

En mis otras FixedSizedLists, la memorización funciona bien con ese contenedor memo / areEqual, pero ¿tal vez el ref={root} está afectando?

Puede saber fácilmente si React está volviendo a renderizar los componentes pegando un

Bifurqué el ejemplo aquí: https://codesandbox.io/s/dynamic-size-of-react-window-list-items-nb038


EDITAR: arreglé la memorización, está destinado a envolver el componente funcional inicial con una nota, no el como lo había hecho yo. Aquí hay una solución memorizada en caso de que alguien tenga una estructura DOM compleja dentro de sus listas (o si tienen que mapear videos como yo): https://codesandbox.io/s/dynamic-size-of-react-window-list -artículos-errt4


EDITAR 2: Resulta que la representación inicial de las filas está completamente bien, pero llamar a resetAfterIndex es muy difícil de administrar. Mis datos cambian (por ejemplo, cuando el usuario selecciona una conversación diferente). Pero el problema real es que resetAfterIndex parece ejecutarse antes de que finalice el nuevo setSize . Por lo tanto, borra con éxito el estilo en caché, pero luego simplemente genera una nueva caché de los estilos antiguos nuevamente porque el navegador no ha terminado de redimensionar el contenido.

No estoy seguro de si eso tiene sentido por escrito, pero tengo que poner un alfiler en este por ahora. Avíseme si alguien está cambiando con éxito su contenido de forma dinámica y manteniendo estilos de altura actualizados.

Tengo muchas otras implementaciones de ventana de reacción, por lo que realmente preferiría encontrar una buena solución aquí en lugar de usar react-virtualized para este caso de uso.


EDICIÓN 3: Esta será mi edición final ya que finalmente se me ocurrió una solución semi-elegante.

1.) Si el itemData necesita cambiar (es decir, cuando la conversación está cambiando), desmonte todo componente y luego vuelva a montarlo con el nuevo itemData. Esto se puede hacer usando una devolución de llamada setState. Esto asegura que los estilos de altura antiguos no se transfieran cuando cambie sus datos.

2.) Pasé {sizeMap, setSize, listRef} a ChatMessage través de ChatContext . De esa manera, en lugar de simplemente establecer el tamaño a ciegas, puedo decirle a ChatMessage que establezca el tamaño Y lo compare con el tamaño anterior. Si el tamaño anterior es diferente del nuevo, llame a resetAfterIndex partir de index y pase true para forzar la actualización.

Entonces mi nuevo ChatMessage se parece a esto:

const ChatMessage = ({ message, index }) => {
    const { setSize, sizeMap, listRef } = useContext(ChatContext);
    const root = React.useRef();
    useEffect(() => {
        let oldSize = sizeMap[index];
        let newSize = root.current.getBoundingClientRect().height;
        setSize(index, newSize);
        if(newSize !== oldSize){
            listRef.current.resetAfterIndex(index,true);
        }
    }, [sizeMap, setSize, listRef]);

    return (
        <div ref={root}
             {message.body}
        </div>
    );
};
export default ChatMessage;

3.) Agregué lo que es básicamente un oyente en el componente que espera al recién montado para ser renderizado. Una vez renderizado, se desplaza hasta la parte inferior. Esto soluciona el problema de intentar poner la función scrollTo directamente en componentDidMount porque nunca se procesa antes de que se llame a ese método. Entonces Se ve como esto:

class Chat extends Component {
    constructor(props) {
        super(props);
        this.listRef = createRef();
        this.state = {
            initialScrollComplete: false,
            interval: null
        };
    }

    componentDidMount(){
        // Create interval to check if list is ready. Once ready, scroll to bottom of list.
        this.setState({interval: setInterval(()=>{
            if(this.listRef.current && !this.state.initialScrollComplete){
                this.listRef.current.scrollToItem(this.props.chatHistory.length - 1, "end");
                this.setState({initialScrollComplete: true});
            }
        },25)});
    }

    componentDidUpdate(prevProps, prevState) {

        // Clear interval if scroll has been completed
        if(!prevState.initialScrollComplete && this.state.initialScrollComplete){
            clearInterval(this.state.interval);
            this.setState({interval: null});
        }

        // If new message is transmitted, scroll to bottom
        if(prevProps.chatHistory && this.props.chatHistory && prevProps.chatHistory.length !== this.props.chatHistory.length){
            this.listRef.current.scrollToItem(this.props.chatHistory.length - 1, "end");
        }

    }

    render() {
        return <ChatHistory listRef={this.listRef} chatHistory={this.props.chatHistory}/>;
    }
}

Parece haber un comportamiento realmente extraño en un safari.

La altura del div DynamicSizedList y la altura o margen superior de las filas no funciona correctamente, el contenido comienza a superponerse.

Cuando cambia el ancho de la ventana / contenido de la fila, la nueva altura no se vuelve a calcular ni se cambia para trabajar con la nueva altura del contenido.

Algo que parece solucionarlo es si el contenido es desplazable, desplazarse hasta un punto donde la fila ya no es visible, desplazarse hacia arriba hace que se renderice correctamente.

El contenido no se muestra correctamente en la primera carga de la página, por lo que la actualización no parece solucionar el problema: /

Todo funciona absolutamente bien en otros navegadores, incluidos Chrome y Firefox. Safari es horrible, pero desafortunadamente la aplicación aún necesita funcionar para las personas que la usan.

Screenshot 2020-02-15 at 14 27 19

¡Realmente me vendría bien un poco de ayuda!

@tastyqbit También encontré el mismo problema en Safari e Internet Explorer. Como mencionó, desplazarse más allá de la fila expandida y luego desplazarse hacia atrás permite que se procese correctamente, pero, por supuesto, eso no resuelve el problema.

Si encuentra alguna solución, hágamelo saber.

@afreix @tastyqbit Estoy bastante seguro de que sus problemas en Safari e Internet Explorer se deben a la falta de compatibilidad con ResizeObserver en esos navegadores. Tenía exactamente su problema (desplazarse hacia atrás lo solucionó) y agregar un polyfill lo resolvió por mí. Consulte MDN para ver las tablas de compatibilidad.

Creo que la falta de ResizeObserver debería generar una advertencia en la consola.

¿Qué pasa con algo como esto https://codesandbox.io/s/agitated-jennings-o9nn6 ?

básico usando VariableSizeList + ItemMeasurer de # 102 Sé que este es un enfoque muy ingenuo, pero parece que está funcionando (no tan mal 😂) como solución temporal 🤔

En nuestro equipo nos encontramos con la necesidad de generar una gran lista de datos textuales de tamaño aleatorio.
Para nosotros, la capacidad de saltar con precisión entre elementos y desplazarse sin retrasos era imprescindible.
Después de un poco de búsqueda en línea, me di por vencido y escribí esta biblioteca .
Espero que les ayude como solución temporal a algunos de ustedes: smile_cat:

Oye,
Solo quería actualizar eso después de un poco de trabajo, creo que la biblioteca llegó a un estado decente y podría ser una buena solución si sus elementos no cambian de tamaño después de ser renderizados por primera vez.

@ gnir-work ¿qué pasa si la ventana cambia de tamaño y el tamaño del contenedor cambia, lo que hace que la lista cambie de tamaño?

Al leer este hilo, creo que podría haber una mejor manera de manejar los elementos que tienen un ancho que puede cambiar.

La definición de 'variable' aquí es variable en todo el conjunto. El tamaño real de los artículos es estático, no dinámico. Quizás dinámico sea un término mejor porque el tamaño puede cambiar durante el cambio de tamaño o la mutación si el texto cambia.

La forma en que esto podría funcionar es escuchar el desplazamiento en el padre.

El algoritmo funcionaría así:

  • Calcule un tamaño estimado para cada artículo; esto debe ser muy eficiente. No tiene por qué ser perfecto. + - 20% está bien.

  • solo representamos elementos que son visibles + digamos un 20% más para que si el usuario se desplaza no vea ningún cambio

  • Tenemos un 'fantasma' para todo lo demás que tiene 'altura' establecida en la altura estimada. Es solo un div vacío. De esta forma, la barra de desplazamiento se ve a la derecha.

  • Un elemento solo se muestra cuando está en la ventana gráfica. Aparte de eso, se muestran los elementos fantasma.

El único inconveniente de esto es que la altura de la barra de desplazamiento cambiará ligeramente. No estoy seguro de si esto distraería al usuario. Podría serlo si la lista de desplazamiento es grande. PODRÍAMOS ser capaces de engañar a esto aumentando / disminuyendo un búfer de manera que los tamaños estimados no afecten la longitud de la barra de desplazamiento.

@ gnir-work ¿qué pasa si la ventana cambia de tamaño y el tamaño del contenedor cambia, lo que hace que la lista cambie de tamaño?

A partir de la última versión ( 2.2.0 ), el componente admite cambios en el tamaño de la lista completa (alto y ancho).

Al leer este hilo, creo que podría haber una mejor manera de manejar los elementos que tienen un ancho que puede cambiar.

La definición de 'variable' aquí es variable en todo el conjunto. El tamaño real de los artículos es estático, no dinámico. Quizás dinámico sea un término mejor porque el tamaño puede cambiar durante el cambio de tamaño o la mutación si el texto cambia.

La forma en que esto podría funcionar es escuchar el desplazamiento en el padre.

El algoritmo funcionaría así:

  • Calcule un tamaño estimado para cada artículo; esto debe ser muy eficiente. No tiene por qué ser perfecto. + - 20% está bien.
  • solo representamos elementos que son visibles + digamos un 20% más para que si el usuario se desplaza no vea ningún cambio
  • Tenemos un 'fantasma' para todo lo demás que tiene 'altura' establecida en la altura estimada. Es solo un div vacío. De esta forma, la barra de desplazamiento se ve a la derecha.
  • Un elemento solo se muestra cuando está en la ventana gráfica. Aparte de eso, se muestran los elementos fantasma.

El único inconveniente de esto es que la altura de la barra de desplazamiento cambiará ligeramente. No estoy seguro de si esto distraería al usuario. Podría serlo si la lista de desplazamiento es grande. PODRÍAMOS ser capaces de engañar a esto aumentando / disminuyendo un búfer de manera que los tamaños estimados no afecten la longitud de la barra de desplazamiento.

Esto ya fue implementado por @bvaughn en react-virtualized . La principal desventaja de este enfoque es que saltar a una fila específica no funciona bien y crea errores visuales al desplazarse hacia arriba.

@ gnir-work ah .. ok ... tal vez abortaré mi trabajo y miraré a react-virtualized.

Creo que tiene razón con los problemas de desplazamiento hacia arriba, pero creo que puedo solucionarlo teniendo un 'tamaño estimado' y luego convertirlo a un tamaño real una vez que se monte el componente.

... pero, por supuesto, otro problema es el manejo de contenido dinámico. Si algo actualiza, la altura del componente cambia.

Si el tamaño estimado es exacto de lo que puede funcionar, por ejemplo, implementé hace algún tiempo una lista virtualizada con altura dinámica con react-virtualized y funcionó bien siempre que el tamaño estimado fuera exacto. De lo contrario, la funcionalidad de desplazamiento a la fila rompería mi aplicación ☹

Enviado desde Mail para Windows 10

De: Kevin Burton
Enviado: martes 14 de abril de 2020 23:07
Para: bvaughn / react-window
Cc: Nir Geller; Mencionar
Asunto: Re: [bvaughn / react-window] Admite contenido medido justo a tiempo (n. ° 6)

@ gnir-work ah .. ok ... tal vez abortaré mi trabajo y miraré a react-virtualized.
Creo que tiene razón con los problemas de desplazamiento hacia arriba, pero creo que puedo solucionarlo teniendo un 'tamaño estimado' y luego convertirlo a un tamaño real una vez que se monte el componente.
... pero, por supuesto, otro problema es el manejo de contenido dinámico. Si algo actualiza, la altura del componente cambia.
-
Recibes esto porque te mencionaron.
Responda a este correo electrónico directamente, véalo en GitHub o cancele la suscripción.

-
El software antivirus Avast ha verificado este correo electrónico en busca de virus.
https://www.avast.com/antivirus

@ gnir-work ah ... No necesito la funcionalidad 'desplazarse a la fila', creo ... aunque tal vez me equivoque.

Que esto debería ser suficiente para tus necesidades 😊

Enviado desde Mail para Windows 10

De: Kevin Burton
Enviado: martes 14 de abril de 2020 23:13
Para: bvaughn / react-window
Cc: Nir Geller; Mencionar
Asunto: Re: [bvaughn / react-window] Admite contenido medido justo a tiempo (n. ° 6)

@ gnir-work ah ... No necesito la funcionalidad 'desplazarse a la fila', creo ... aunque tal vez me equivoque.
-
Recibes esto porque te mencionaron.
Responda a este correo electrónico directamente, véalo en GitHub o cancele la suscripción.

-
El software antivirus Avast ha verificado este correo electrónico en busca de virus.
https://www.avast.com/antivirus

Como solución si:

  • la altura de la fila de su lista depende solo del texto interno (más tal vez algunos elementos con dimensiones determinadas)
  • y tu lista tiene un ancho fijo

puede usar CanvasRenderingContext2D.measureText () para calcular la altura de la fila en lugar de representar el componente completo: poop:

Código Caja de arena

@bvaughn ¿Tiene planes de publicar una nueva versión alfa en npm? No hemos tenido ninguna actualización desde 1.6.0-alpha.1 😕

@bvaughn ¿ alguna actualización? ¿Se solucionará en versiones recientes?

Para aquellos que quieran usar TypeScript con DynamicSizeList , el aumento de módulo puede proporcionar los tipos necesarios para DynamicSizeList trabajando fuera de las definiciones DefinitelyTyped (una solución alternativa a mi consulta publicada en este hilo el año pasado).

Agregue lo siguiente al proyecto:

import React, { Component } from 'react'

declare module 'react-window' {
  export type DynamicSizeListProps = Omit<FixedSizeListProps, 'itemSize' | 'scrollToItem'>
  export class DynamicSizeList extends Component<DynamicSizeListProps> {}
}

Luego importe como de costumbre:

import {
  DynamicSizeList,
  DynamicSizeListProps,
} from 'react-window'

// use as normal...

@types/react-window aún debe instalarse primero para la definición FixedSizeListProps .

Gracias por los typedefs, ¡los voy a agregar ahora! He estado usando DynamicSizeList en producción durante más de un año. Actualmente basado en esta bifurcación: "@john-osullivan/react-window-dynamic-fork": "^1.9.0-alpha.1" (¿es eso lo más actualizado todavía?). Traté de cambiar a react-virtuoso debido a la incertidumbre sobre si esto realmente se lanzaría / cuándo. Pero lo encontré con menos rendimiento y atascado con esto.

@bvaughn, ¿ es hora de pavimentar el camino de las vacas y lanzar esto a npm? Tal vez simplemente se le haya cambiado el nombre a ExperimentalDynamicSizeList si todavía le preocupa que no esté listo.

¡Hola, chicos! Gracias por su arduo trabajo y esta gran biblioteca. ¡Tengo muchas ganas de esta función! Sin embargo, sugeriría agregar información sobre este tema en el archivo README y en la documentación / ejemplos. Me tomó bastante tiempo darme cuenta de que el contenido dinámico en realidad no es compatible con la biblioteca y solo es útil para elementos con tamaño fijo / conocido. Creo que el archivo README tiene una buena sección de preguntas frecuentes donde se podría agregar.

si está buscando una tabla / cuadrícula / árbol, este sería un buen comienzo https://autodesk.github.io/react-base-table/examples/dynamic-row-heights , construido en VariableSizeGrid

@ tony-scio, ¿puedes compartir un codeandbox que funcione para usar DynamicSizeList de 1.6.0-alpha.1 con InfiniteLoader? Gracias, te lo agradecería mucho.

¿Alguien ha conseguido que esto funcione con react-beautiful-dnd? Arrastrar parece hacer que los elementos salten uno encima del otro.

¿Alguien ha conseguido que esto funcione con react-beautiful-dnd? Arrastrar parece hacer que los elementos salten uno encima del otro.

también esperaré esta respuesta: D

[AYUDA]
No hay código para mostrar en este enlace:
vertical-lista-de-tamaños-dinámica
y necesito esta habilidad.
GRACIAS

[AYUDA]
No hay código para mostrar en este enlace:
vertical-lista-de-tamaños-dinámica
y necesito esta habilidad.
GRACIAS

https://react-window-next.now.sh/#/examples/list/dynamic -size

¿Algún avance en esto? Necesitamos algo similar a lo que podamos (generalmente son muy pocos, pero en algunos casos pueden ser muchos) renderizar una gran lista de elementos de cuadrícula receptiva (sus alturas son dinámicas y cambiarán en dispositivos móviles como varios ajustes de texto, etc.). Siento que react-window cambiaría las reglas del juego si pudiera manejar este caso de uso. Si no es así, ¿existen alternativas fiables?

¿Algún avance en esto? Necesitamos algo similar a lo que podamos (generalmente son muy pocos, pero en algunos casos pueden ser muchos) renderizar una gran lista de elementos de cuadrícula receptiva (sus alturas son dinámicas y cambiarán en dispositivos móviles como varios ajustes de texto, etc.). Siento que react-window cambiaría las reglas del juego si pudiera manejar este caso de uso. Si no es así, ¿existen alternativas fiables?

@JavaJamie ya que solicitó específicamente alternativas, la biblioteca react-virtuoso viene con soporte incorporado para medir contenido dinámico. Descargo de responsabilidad: soy el autor del mismo.

@JavaJamie ya que solicitó específicamente alternativas, la biblioteca react-virtuoso viene con soporte incorporado para medir contenido dinámico. Descargo de responsabilidad: soy el autor del mismo.

react-virtuoso también es el doble del tamaño de react-window. Siempre hay que tener en cuenta el tamaño de la dependencia.

https://bundlephobia.com/[email protected]
https://bundlephobia.com/[email protected]

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 302 para ver cómo encajaría en la versión dos como los nuevos componentes List y Grid )

Terminamos implementando algo desde cero para esto, que usamos sensores de visibilidad que funcionaron muy bien.

Probablemente podría OSS o señalarles el lugar correcto si quieren arrancarlo y crear un nuevo proyecto o moverlo aquí.

Un truco es que usamos 'bloques' para poder aumentar el rendimiento. Básicamente, tomamos cada fila y, de hecho, la colocamos en un bloque principal de 25 elementos, y luego lo intercambiamos cuando sea necesario.

@burtonator sería realmente útil

¿Alguien puede proporcionar una implementación sin errores de react-select con DynamicSizeList?
No puedo hacer que funcionen bien juntos.
Actualmente me enfrento a 2 problemas (lo siento por no hacer capturas de pantalla):

  1. Todos los elementos tienen style={position: absolute, left: 0, top: 0} lo que no me permite usar este estilo, ya que todas las opciones se encuentran una encima de la otra.
  2. Si no uso el accesorio de estilo, la lista se muestra bien, pero cuando me desplazo un poco, la parte de la lista con opciones se encoge, mientras que la altura total permanece sin cambios. Por lo tanto, cuando me desplazo, obtengo x píxeles de opciones reales y espacio en blanco de longitud x píxeles.

No se pudo encontrar ningún ejemplo funcional de los dos.
Notaré que uso la bifurcación 1.9.0, en Chrome.

Editar. Encontré una respuesta aquí arriba, en la sección de comentarios ocultos. https://github.com/bvaughn/react-window/issues/6#issuecomment -509016422

Una simplificación del problema del desplazamiento sería usar la barra de desplazamiento para indicar el índice del elemento en la lista en lugar de la posición de un píxel, si el desplazamiento está a más de una altura de ventana gráfica. En lugar de intentar "desplazarse hacia abajo" X píxeles, el componente simplemente representa los elementos alrededor del índice deseado. A mitad de camino hacia abajo representa el elemento en el índice N / 2, y en la parte inferior representa el elemento en el índice N-1.

Eso permitiría el desplazamiento directo del pulgar al centro o al final de la lista, sin el retraso del pulgar de desplazamiento mientras el componente representa y calcula los tamaños. En este momento, para los componentes VariableSizeList muy largos, es casi imposible desplazarse hasta la parte inferior ya que el cursor se arrastra más rápido de lo que se mueve el pulgar de desplazamiento.

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