反应虚拟化 scrollToIndex 不适用于列表
react-virtualized scrollToIndex not working on List
尝试滚动到索引时,屏幕变为空白。
这是一个重现问题的codesandbox。只需在顶部的输入框中键入 100,然后单击 "scroll to row" 按钮。
https://codesandbox.io/s/zr2r2wp1x
这是一个有点复杂的视图 - 它使用了 InfiniteLoader、WindowScroller、Autosizer、CellMeasurer、CellMeasurerCache 和 List。
代码如下:
import React, { Component } from 'react';
import {
AutoSizer,
CellMeasurer,
CellMeasurerCache,
InfiniteLoader,
List,
WindowScroller
} from 'react-virtualized';
const cache = new CellMeasurerCache({
fixedWidth: true,
defaultHeight: 100
});
class Hello extends Component {
constructor(props) {
super(props);
this.state = {
scrollToIndex: undefined
}
this.list = [];
this.makeList = this.makeList.bind(this);
this.makeList();
this.handleClick = this.handleClick.bind(this);
}
makeList() {
for (let i = 0; i < 200; i++) {
this.list.push("yo");
}
}
handleClick() {
this.setState({
scrollToIndex:this.inputRow.value
})
}
isRowLoaded({ index }) {
return !!this.list[index];
}
loadMoreRows({ startIndex, stopIndex }) {
this.makeList();
}
rowRenderer({ index, isScrolling, isVisible, key, parent, style }) {
if (isScrolling) {
return null;
}
if (isVisible) {
return (
<CellMeasurer
key={key}
cache={cache}
parent={parent}
columnIndex={0}
rowIndex={index}
>
<div style={style}>
this is row: {index}
</div>
</CellMeasurer>
);
}
return null;
}
render() {
if (this.list.length === 0) {
return <div>No data available.</div>;
}
const scrollToIndex = this.state.scrollToIndex;
return (
<div>
<div>
<input
type="number"
ref={(input) => { this.inputRow = input; }} />
<input
type="button"
value="Scroll To Row"
onClick={this.handleClick}
/>
</div>
<InfiniteLoader
isRowLoaded={isRowLoaded => this.isRowLoaded(isRowLoaded)}
loadMoreRows={loadMoreRows => this.loadMoreRows(loadMoreRows)}
rowCount={10000}
threshold={1}
>
{({ onRowsRendered, registerChild }) => (
<WindowScroller>
{({ height, isScrolling, onChildScroll, scrollTop }) => (
<AutoSizer disableHeight>
{({ width }) => {
console.log("scroll to index", scrollToIndex)
return (
<List
autoHeight
height={height}
onRowsRendered={onRowsRendered}
ref={registerChild}
width={width}
rowCount={this.list.length}
rowHeight={cache.rowHeight}
rowRenderer={rowRenderer => this.rowRenderer(rowRenderer)}
scrollTop={scrollTop}
deferredMeasurementCache={cache}
style={{ paddingLeft: '0', paddingRight: '0' }}
scrollToAlignment="start"
scrollToIndex={scrollToIndex}
/>
)
}}
</AutoSizer>
)}
</WindowScroller>
)}
</InfiniteLoader>
</div>
);
}
}
export default Hello;
这里 updated CodeSandbox 展示了如何实现您想要的行为。我必须修复您的入门代码的许多问题才能使示例正常工作 - 简短的回答是您缺少将 WindowScroller
的渲染道具 onChildScroll
传递给 List
组件的 onScroll
道具。此设置将允许两个组件相互通信以有效地正确更新列表。
尝试滚动到索引时,屏幕变为空白。
这是一个重现问题的codesandbox。只需在顶部的输入框中键入 100,然后单击 "scroll to row" 按钮。 https://codesandbox.io/s/zr2r2wp1x
这是一个有点复杂的视图 - 它使用了 InfiniteLoader、WindowScroller、Autosizer、CellMeasurer、CellMeasurerCache 和 List。
代码如下:
import React, { Component } from 'react';
import {
AutoSizer,
CellMeasurer,
CellMeasurerCache,
InfiniteLoader,
List,
WindowScroller
} from 'react-virtualized';
const cache = new CellMeasurerCache({
fixedWidth: true,
defaultHeight: 100
});
class Hello extends Component {
constructor(props) {
super(props);
this.state = {
scrollToIndex: undefined
}
this.list = [];
this.makeList = this.makeList.bind(this);
this.makeList();
this.handleClick = this.handleClick.bind(this);
}
makeList() {
for (let i = 0; i < 200; i++) {
this.list.push("yo");
}
}
handleClick() {
this.setState({
scrollToIndex:this.inputRow.value
})
}
isRowLoaded({ index }) {
return !!this.list[index];
}
loadMoreRows({ startIndex, stopIndex }) {
this.makeList();
}
rowRenderer({ index, isScrolling, isVisible, key, parent, style }) {
if (isScrolling) {
return null;
}
if (isVisible) {
return (
<CellMeasurer
key={key}
cache={cache}
parent={parent}
columnIndex={0}
rowIndex={index}
>
<div style={style}>
this is row: {index}
</div>
</CellMeasurer>
);
}
return null;
}
render() {
if (this.list.length === 0) {
return <div>No data available.</div>;
}
const scrollToIndex = this.state.scrollToIndex;
return (
<div>
<div>
<input
type="number"
ref={(input) => { this.inputRow = input; }} />
<input
type="button"
value="Scroll To Row"
onClick={this.handleClick}
/>
</div>
<InfiniteLoader
isRowLoaded={isRowLoaded => this.isRowLoaded(isRowLoaded)}
loadMoreRows={loadMoreRows => this.loadMoreRows(loadMoreRows)}
rowCount={10000}
threshold={1}
>
{({ onRowsRendered, registerChild }) => (
<WindowScroller>
{({ height, isScrolling, onChildScroll, scrollTop }) => (
<AutoSizer disableHeight>
{({ width }) => {
console.log("scroll to index", scrollToIndex)
return (
<List
autoHeight
height={height}
onRowsRendered={onRowsRendered}
ref={registerChild}
width={width}
rowCount={this.list.length}
rowHeight={cache.rowHeight}
rowRenderer={rowRenderer => this.rowRenderer(rowRenderer)}
scrollTop={scrollTop}
deferredMeasurementCache={cache}
style={{ paddingLeft: '0', paddingRight: '0' }}
scrollToAlignment="start"
scrollToIndex={scrollToIndex}
/>
)
}}
</AutoSizer>
)}
</WindowScroller>
)}
</InfiniteLoader>
</div>
);
}
}
export default Hello;
这里 updated CodeSandbox 展示了如何实现您想要的行为。我必须修复您的入门代码的许多问题才能使示例正常工作 - 简短的回答是您缺少将 WindowScroller
的渲染道具 onChildScroll
传递给 List
组件的 onScroll
道具。此设置将允许两个组件相互通信以有效地正确更新列表。