具有动态高度的反应虚拟化无限滚动问题
Posted
技术标签:
【中文标题】具有动态高度的反应虚拟化无限滚动问题【英文标题】:react-virtualized Infinite scroller issues with dynamic height 【发布时间】:2018-01-18 13:57:08 【问题描述】:我正在尝试使用 react-virtualized 在我的应用程序中模拟 Facebook 提要,如滚动条。我正在关注here 的参考。我正在尝试一次加载两个提要,然后将调用 loadMoreRows
来获取接下来的两个提要。出于测试目的,我已将 Feed 大小硬编码为 10。它工作良好,直到第 4 次喂食。然后我无法顺利移动。 rowRenderer
一次又一次地触发数字,导致屏幕上的振动效果。如果我以某种方式移动到第 10 个提要并向后滚动,rowRenderer
将再次从 0 开始。我认为这是由于高度不同。与参考类似,我使用CellMeasurerCache
和CellMeasurer
来查找动态height
和width
并将其传递给列表。
class Scroller extends React.Component
_cache = new CellMeasurerCache( defaultHeight: 100, fixedWidth: true );
_resizeAllFlag = false;
_mostRecentWidth = 0;
constructor(props)
super(props);
this.state =
localCache: []
componentDidMount()
this._loadData(0);
componentDidUpdate(prevProps, prevState)
console.log(this._list);
if(this._resizeAllFlag)
this._resizeAllFlag = false;
this._cache.clearAll();
this._recomputeRowHeights();
else if(this.state.localCache !== prevState.localCache)
this._cache.clear(index, 0);
this._recomputeRowHeights(index);
._loadData = (offset, callback) =>
//Loads data from server and sets it in this.state.localCache
_recomputeRowHeights = (index) =>
if (this._list)
console.log('Recomputing');
this._list.recomputeRowHeights(index);
_isRowLoaded = ( index ) =>
return !!this.state.localCache[index];
_loadMoreRows = ( startIndex, stopIndex ) =>
this._loadData(startIndex, (() => promiseResolver));
let promiseResolver;
return new Promise((resolve) =>
promiseResolver = resolve;
);
rowRenderer = ( index, key, style, parent ) =>
const row = this.state.localCache[index];
let content;
if (row)
content = (<Feed data=row/>);
else
content = (<CustomLoader />);
return (
<CellMeasurer
cache=this._cache
columnIndex=0
key=key
parent=parent
rowIndex=index
width=this._mostRecentWidth
>
content
</CellMeasurer>);
_setListRef = (ref) =>
this._list = ref;
this._registerList(ref);
;
_resizeAll = () =>
this._resizeAllFlag = false;
this._cache.clearAll();
if (this._list)
this._list.recomputeRowHeights();
;
render()
const localCache = this.state;
return (
<div className="flex_grow">
<InfiniteLoader
isRowLoaded=this._isRowLoaded
loadMoreRows=this._loadMoreRows
rowCount=10
>
( onRowsRendered, registerChild ) =>
<AutoSizer disableHeight>
( width, height ) =>
if (this._mostRecentWidth && this._mostRecentWidth !== width)
this._resizeAllFlag = true;
setTimeout(this._resizeAll, 0);
this._mostRecentWidth = width;
this._registerList = registerChild;
return (
<List
deferredMeasurementCache=this._cache
overscanRowCount=1
ref=this._setListRef
height=height
onRowsRendered=onRowsRendered
rowCount=10
rowHeight=this._cache.rowHeight
rowRenderer=this.rowRenderer
width=width
/>
)
</AutoSizer>
</InfiniteLoader>
</div>
);
更新
我可能已经删除了正在传递的内容中的样式道具。根据@Adrien 的建议,我添加了它。添加样式道具后我的问题没有解决。
rowRenderer = ( index, key, style, parent ) =>
const row = this.state.localCache[index];
let content;
if (row)
content = (<Feed style=style data=row/>);
else
content = (<CustomLoader style=style/>);
return (
<CellMeasurer
cache=this._cache
columnIndex=0
key=key
parent=parent
rowIndex=index
width=this._mostRecentWidth
>
content
</CellMeasurer>);
还有我的 Feed 组件
class Feed extends React.Component
constructor(props)
super(props);
render()
const style = this.props;
return (
<div className="flex_grow" style=style>
/* Feed related JSX */
</div>
);
我的组件似乎重叠。可能出了什么问题?
答疑者: https://gist.github.com/beb4/cc91f4e9b8982d172613cff248090769
【问题讨论】:
【参考方案1】:您忘记在 content
组件中传递 rowRenderer
样式。根据the docs 的说法,这种样式是强制定位行的。
更正行渲染器
rowRenderer = ( index, key, style, parent ) =>
const row = this.state.localCache[index];
let content;
if (row)
content = (<Feed data=row style=style />); // <== HERE
else
content = (<CustomLoader style=style />); // <== AND HERE
return (
<CellMeasurer
cache=this._cache
columnIndex=0
key=key
parent=parent
rowIndex=index
width=this._mostRecentWidth
>
content
</CellMeasurer>
);
【讨论】:
感谢您的帮助。我最初有风格。不知何故,在编辑时我可能已经删除了它。我按照你的建议再次添加。即使添加了style
props
,我也遇到了同样的问题。
@user2193672 你是否在Feed
组件内的根节点上应用style
属性?你能粘贴你的代码吗?
是的。我将 style
道具传递给了我的 Feed
和 CustomLoader
,而不是按照您的建议传递给 CellMeasurer
。已经用它更新了问题。
@user2193672 我的意思是应用style
不仅仅是传递style
属性,而是在Feed
组件中处理它。你能粘贴你的Feed
组件吗? (仅渲染)
让我们continue this discussion in chat.以上是关于具有动态高度的反应虚拟化无限滚动问题的主要内容,如果未能解决你的问题,请参考以下文章