Estoy usando react-virtualized para evitar que se carguen elementos en una lista larga cuando está fuera del puerto de visualización. Sin embargo, tengo un botón en la parte superior de la página que, cuando se hace clic, se desplaza hacia un elemento que se representa con react-virtualized.
Utiliza React.createRef() para vincular el botón con el elemento de la lista, pero debido a que el elemento representado no existe en el dom, la referencia es null (funciona para los primeros elementos que se procesan, pero no para el resto de los elementos ).
Por ejemplo, si hago clic en el botón 20, aparece el error Cannot read properties of null (reading 'getBoundingClientRect') porque la referencia del botón es nula porque su contraparte ref no existe
¿Hay alguna manera de desplazarse a los elementos que se han renderizado dentro de react-virtualized?
He creado un entorno limitado de código aquí para mostrar lo que quiero decir.
De lo contrario, aquí está el fragmento de código:
export default function App() { const onClick = (item) => { window.scrollTo({ top: item.ref.current.getBoundingClientRect().top, behavior: "smooth" }); }; const items = arr.map((el) => ({ ref: createRef(), id: el.id })); return ( <div className="App"> {items.map((item) => ( <button onClick={(e) => onClick(item)}>Scroll to {item.id}</button> ))} <WindowScroller> {({ height, scrollTop, registerChild }) => ( <div ref={registerChild}> <AutoSizer disableHeight> {({ width }) => ( <> <List autoHeight width={width} height={height} rowHeight={100} rowRenderer={({ index }) => { return ( <div ref={items[index].ref} id={`item-${items[index].id}`} key={items[index].id} > {items[index].id} </div> ); }} scrollTop={scrollTop} rowCount={items.length} overscanRowCount={100} /> </> )} </AutoSizer> </div> )} </WindowScroller> </div> ); }Agregue una referencia a su <List> y utilícela para desplazarse al índice del elemento.
const listRef = React.createRef<List>(); function scrollToItem(item) { const index = calculateIndex(item) // figure out what index the item should have listRef.current.scrollToItem(index) // second parameter here could be 'auto', 'smart', 'center', 'end', 'start' } return ( /* ... */ <List ref={listRef} /* ... */ /> /* ... */ )Usemos el componente Lista para representar la lista de forma virtualizada:
const listHeight = 600; const rowHeight = 50; const rowWidth = 800; //... <div className="list"> <List width={rowWidth} height={listHeight} rowHeight={rowHeight} rowRenderer={this.renderRow} rowCount={this.list.length} /> </div>Fíjate en dos cosas.
Primero, el componente List requiere que especifique el ancho y el alto de la lista. También necesita la altura de las filas para poder calcular qué filas serán visibles.
La propiedad rowHeight toma una altura de fila fija o una función que devuelve la altura de una fila dado su índice.
En segundo lugar, el componente necesita el número de filas (la longitud de la lista) y una función para representar cada fila. No toma la lista directamente.