Я пытаюсь создать канал (короче, похожий на Pinterest). Я использую компонент масонства react-virtualized.
Вы можете увидеть, как элементы переставляются и размер компонента изменяется правильно, когда размер окна браузера изменяется в записи экрана это.
Однако у меня странное поведение, как вы можете видеть в записи экрана это.
Вот соответствующий отрывок из моего кода:
export default class Feed extends Component <PropTypes, State> {
static readonly defaultProps = {
enableInfiniteScroll: false,
chunkSize: 9,
};
private _windowScroller: WindowScroller;
private _masonry: Masonry;
private _columnCount: number;
private _cache: CellMeasurerCache;
private _cellPositioner: Positioner;
constructor(props: PropTypes) {
super(props);
// ...
this._columnCount = 3;
this._cache = new CellMeasurerCache({
defaultWidth: COLUMN_WIDTH,
defaultHeight: 400,
fixedWidth: true,
});
this._cellPositioner = createMasonryCellPositioner({
cellMeasurerCache: this._cache,
columnCount: this._columnCount,
columnWidth: COLUMN_WIDTH,
spacer: GUTTER,
});
}
onResize({width}: Size) {
this._cache.clearAll();
this.calculateColumnCount(width);
this.resetCellPositioner();
this._masonry.recomputeCellPositions();
}
cellRenderer(cellProps: MasonryCellProps) {
const {items} = this.state;
const listing = items.get(cellProps.index);
return (
<CellMeasurer
cache = {this._cache}
index = {cellProps.index}
key = {cellProps.key}
parent = {cellProps.parent}
>
<div style = {cellProps.style}>
<ListingCard company = {listing} />
</div>
</CellMeasurer>
);
}
calculateColumnCount(width: number) {
this._columnCount = Math.floor((width + GUTTER) / (COLUMN_WIDTH + GUTTER));
}
resetCellPositioner() {
this._cellPositioner.reset({
columnCount: this._columnCount,
columnWidth: COLUMN_WIDTH,
spacer: GUTTER,
});
}
render() {
const {items, isLoading, hasMore} = this.state;
return (
<div className = {Styles['listings-feed']}>
<WindowScroller scrollElement = {window} ref = {this.setRef}>
{({height, isScrolling, onChildScroll, scrollTop, registerChild}) => (
<div className = {Styles.windowScrollerContainer}>
<AutoSizer disableHeight onResize = {this.onResize}>
{({width}) => (
<div ref = {registerChild as any}>
<Masonry
cellCount = {items.size}
cellMeasurerCache = {this._cache}
cellPositioner = {this._cellPositioner}
cellRenderer = {this.cellRenderer}
height = {height}
width = {width}
autoHeight
ref = {(r: Masonry) => this._masonry = r}
/>
</div>
)}
</AutoSizer>
</div>
)}
</WindowScroller>
</div>
);
}
}





После тестирования с различными параметрами и настройками я обнаружил, что не все элементы отображаются, потому что они технически находятся вне диапазона (не в представлении пользователя). Они не скрывались при прокрутке, просто компонент <Masonry /> обновляется только при изменении свойств.
Поскольку я использую компонент <WindowScroller />, я обнаружил, что он предлагает переменную scrollTop для функции children, поэтому я передал ее непосредственно компоненту Masonry:
<WindowScroller scrollElement = {window} ref = {this.setRef}>
{({height, isScrolling, onChildScroll, scrollTop, registerChild}) => (
<div className = {Styles.windowScrollerContainer}>
<AutoSizer disableHeight onResize = {this.onResize}>
{({width}) => (
<div ref = {registerChild as any}>
<Masonry
cellCount = {items.size}
cellMeasurerCache = {this._cache}
cellPositioner = {this._cellPositioner}
cellRenderer = {this.cellRenderer}
height = {height}
width = {width}
autoHeight
ref = {(r: Masonry) => this._masonry = r}
scrollTop = {scrollTop}
/>
</div>
)}
</AutoSizer>
</div>
)}
</WindowScroller>