Width of the Table in AutoSizer and Window Scroller is not being updated properly while resizing the browser - react-virtualized

I am using React-Virtualized to display a table with a long list of values. So it's a combination of WindowScroller, AutoSizer and Table. I am having an issue when the browser is resized. This is my code:
render() {
return (
<WindowScroller>
{({ height, isScrolling, scrollTop }) => (
<AutoSizer>
{({ width }) => (
<Table
ref={(ref: Table) => { this.TableRef = ref; }}
autoHeight={true}
height={height}
width={width}
isScrolling={isScrolling}
scrollTop={scrollTop}
_noRowsRenderer={this._noRowsRenderer}
...
>
<Column
...
/>
</Table>
)}
</AutoSizer>)}
</WindowScroller>
);
}
When the browser is resized the width of the table is not updated accordingly and so a vertical scroll bar is being displayed although it's not needed; unless it's zoom-in or zoom-out and then it's all redrawn-positioned correctly.
Does anyone has any idea how to fix this?

Related

How Do I Correctly use CellMeasurer to set Table Column Width Based on the Content Length?

I'm trying to dynamically set the column width using CellMeasurer in a dynamic created Columns.
// hoping that CellMeasurer is what I needed to adjust
// width of my table columns, but not working.
const cellRenderer = ({ columnIndex, key, parent, rowIndex, style }) => {
const content = list[rowIndex][columnHeader[columnIndex].columnName];
return (
<CellMeasurer
cache={cache}
columnIndex={columnIndex}
key={key}
parent={parent}
rowIndex={rowIndex}
>
<div
style={{
...style,
height: 35,
whiteSpace: "nowrap"
}}
>
{content}
</div>
</CellMeasurer>
);
};
const cache = new CellMeasurerCache({
defaultWidth: 100,
minWidth: 75,
fixedHeight: true
});
return (
<AutoSizer>
{({ height, width }) => (
<div width={width}>
<Table
width={width}
height={500} // why can't i use {height} here?
headerHeight={40}
rowHeight={30}
rowCount={list.length}
rowGetter={({ index }) => list[index]}
>
// Dynamically create Column
{columnHeader.map((columnData, i) => (
<Column
width={800}
onClick={this.onHeaderClick}
label={columnData.displayName}
dataKey={columnData.columnName}
cellRenderer={cellRenderer}
{...this.props}
key={i}
/>
))}
</Table>
</div>
)}
</AutoSizer>
);
Here is the example code: https://codesandbox.io/s/mzj5y255kj
I want to set the column 'News' to as long as the length in the text.
Result would be that no matter what the content length is, the column will grow.

WindowScroller + AutoSizer + List not working as expected

I was trying to use the combination of the WindowScroller + AutoSizer + List on my web application. The virtualization works well when it is only AutoSizer + List. However, when I put it inside the WindowScroller, the list of rows no longer display properly.
This is how it looks when WindowScroller is applied.
list result
I already searched for available solutions here and on the doc. Found similar problem posted here but the answer provided was already been applied on my code. Now, I can't figure out what exactly hinders the display of the rows.
return (
<React.Fragment>
<WindowScroller>
{({height, isScrolling, onChildScroll, scrollTop}) => (
<AutoSizer disableHeight>
{({width}) => (
<List
autoHeight
height={height}
isScrolling={isScrolling}
onScroll={onChildScroll}
rowCount={rows.length}
rowHeight={30}
rowRenderer={({ index, style }) => <div style={style}>Row {index}</div>}
scrollTop={scrollTop}
width={width}
>
</List>
)}
</AutoSizer>
)}
</WindowScroller>
</React.Fragment>
);
It appears this is an implementation issue. The overflow style of the container element which I was using for the reference of the WindowScroller is not set properly.

React Virtualized windowscroller scrollElement not working

You were right that I was not passing the props in correctly. Now I have it set up as such:
Container.jsx
<div className='container' ref={(ref) => {this.foo = ref;}}>
this.renderContainer()
</div>
<Section scrollContainer={this.foo}/>
Section.jsx (just passing down props)
<Panel scrollContainer={this.props.scrollContainer}/>
Section.propTypes = { scrollContainer: PropTypes.object.isRequired }
Panel.jsx (Passing down props)
<RenderedTable scrollContainer={this.props.scrollContainer} />
RenderedTable.jsx
return (
<div className='padding-top-20 font-smoothing'>
<WindowScroller scrollElement={this.props.scrollContainer}>
{({ height, isScrolling, scrollTop, onChildScroll }) => (
<AutoSizer disableHeight>
{({ width }) => (
<Table
Unfortunately the windowScroller still does not resize. I also dont get any warnings or errors. Do you use css tricks to get the scroller to resize? I see that in the example https://bvaughn.github.io/react-virtualized/#/components/WindowScroller
you change the flex and overflow properties when changing the scrollElement from window to scrollingBody.
I know you are very busy and greatly appreciate your help!
In your example, you've assigned the scroll ref to this.tabsContainer but you're trying to access it as this.props.tabContainer. Either this is your mistake, or the example is incomplete and more context is needed. :) Can you provide a Plnkr?

React-Virtualized InfiniteLoader lags on passing props to rendered rows

I just got started with react-virtualized and setup an InfiniteLoader->AutoSizer->VirtualScroller. Unfortunately, the rows that are lazily loaded aren't getting their props immediately. They render as if the props were null or undefined. If I scroll on past them and then scroll back to them, they are rendered correctly. Also, other than the initial pre-fetched rows, if I scroll slowly, all new rows render okay. If I send the scroll wheel flying, however, it will "land" on a set of "sub-rendered" rows. Given the code below, what am I doing wrong?
import React, { PropTypes } from 'react'
import { stitch } from 'keo'
import CSSModules from 'react-css-modules'
import css from './component.scss'
import R from 'ramda'
import { Divider, Paper } from 'material-ui'
import { AutoSizer, InfiniteLoader, VirtualScroll } from 'react-virtualized'
import 'react-virtualized/styles.css'
import Row from 'components/Row'
let list = R.repeat({score: 100, volume: 999}, 10)
function isRowLoaded ({ index }) {
return !!list[index]
}
function loadMoreRows ({ startIndex, stopIndex }) {
// fake loading
list = R.insertAll(startIndex, R.repeat({score: 100, volume: 999}, stopIndex - startIndex), list)
return Promise.resolve()
}
const render = ({ props }) => (
<div>
<Paper zDepth={2}>
<Paper zDepth={2}>
</Paper>
<div>
<InfiniteLoader
isRowLoaded={isRowLoaded}
loadMoreRows={loadMoreRows}
rowCount={1000}
>
{({ onRowsRendered, registerChild }) => (
<AutoSizer>
{({ height, width }) => (
<VirtualScroll
ref={registerChild}
width={width}
height={height}
rowCount={1000}
rowHeight={72}
onRowsRendered={onRowsRendered}
rowRenderer={
({ index }) =>
<div>
<Row {...list[index]} />
<Divider />
</div>
}
/>
)}
</AutoSizer>
)}
</InfiniteLoader>
</div>
</Paper>
</div>
)
export const View = CSSModules(stitch({ render }), css)

Does react-virtualized work with airbnb/enzyme?

Is it possible to use react-virtualized and enzyme together? When I try to use them together I seem to get an empty list of items in the grid.
The 2 should work together, yes. I believe the likely problem is that the react-virtualized component is being given a width or height of 0 which causes it not to render anything. (It only renders enough to fill the "window" it has.)
Assuming you're using the AutoSizer HOC- (most people do)- then one pattern I've found helpful is to export 2 versions of components- one that expects explicit width/height properties and one that wraps the other with an AutoSizer. Pseudo code would be:
import { AutoSizer, VirtualScroll } from 'react-virtualized'
// Use this component for testing purposes so you can explicitly set width/height
export function MyComponent ({
height,
width,
...otherProps
}) {
return (
<VirtualScroll
height={height}
width={width}
{...otherProps}
/>
)
}
// Use this component in your browser where auto-sizing behavior is desired
export default function MyAutoSizedComponent (props) {
return (
<AutoSizer>
({ height, width }) => (
<MyComponent
height={height}
width={width}
{...props}
/>
)
</AutoSizer>
)
}
as of react-virtualized 9.12.0 the Autosizer has defaultWidth and defaultHeight properties.
I found setting those meant enzyme tests ran correctly - rendering the child rows as expected.
<AutoSizer disableHeight defaultWidth={100}>
{({ width }) => (
....
)}
</AutoSizer>
Putting this in my test case worked for me:
import { AutoSizer } from 'react-virtualized';
// ...
it('should do something', function() {
spyOn(AutoSizer.prototype, 'render').and.callFake(function render() {
return (
<div ref={this._setRef}>
{this.props.children({ width: 200, height: 100 })}
</div>
);
});
// do something...
I use Jasmine's spyOn here, but other libraries have their own ways of overwriting functions.
Keep in mind that this is pretty fragile against future changes to the react-virtualized library (this._setRef was just yanked from the source code), and may give you false positives.

Resources