我正在尝试使用react-virtualized在我的应用程序中像滚动器一样模拟Facebook Feed。我正在关注here的引用。我试图一次加载两个Feed,然后调用loadMoreRows
来获取接下来的两个。为了测试目的,我已将我的Feed大小硬编码为10。它运作良好,直到第四次进料。然后我不能顺利地移动。 rowRenderer
一次又一次地触发数字,这会导致屏幕上的振动效果。如果我以某种方式移动到第10个Feed并向后滚动,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>
);
}
}
我的组件似乎重叠了。什么可能是错的?
AnswerGist : https://gist.github.com/beb4/cc91f4e9b8982d172613cff248090769
答案 0 :(得分:1)
您忘记在rowRenderer
组件中传递content
样式。根据{{3}},此样式必须用于定位行。
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>
);
}