Repository navigation
Problem refreshing while filtering datas #1104
Copy link
Copy link
Closed as not planned
Description
Hello,
I have a problem using the Grid component. I doing an iTunes like software and I'm trying to implement a search function.

The datas are well filtered, the props are updated in all components but the rendering is very strange. If the result of the filtering return 3 rows (like in the below image), the grid render the first 3 rows of the initial data set and not taking into account the new data set.

My code :
class TableContainer extends React.Component {
render() {
let filteredrowRenderers = [];
if (this.state.rowRenderers) {
filteredrowRenderers = this._getFilteredData();
}
return (
<section id="list">
<section id="searchData">
<FontIcon className="material-icons">search</FontIcon>
<TextField className="textField" name={"search"} placeholder={"Recherche"}
onKeyPress={ e => this._searchData(e.target.value) }
/>
</section>
<MyVirtualizeTable headers={ this.headers }
data={ filteredrowRenderers }/>
</section>
);
}
_getFilteredData() {
const {rowRenderers, searchText} = this.state;
if (searchText) {
return rowRenderers.filter(rowRenderer => rowRenderer.data.searchText.indexOf(searchText.toLowerCase()) >= 0);
}
return rowRenderers;
}
_searchData(text) {
this.setState({
...this.state,
searchText: text
});
}
}
export default class MyVirtualizeTable extends React.PureComponent {
...
render() {
const rowCount = this.props.data.length;
return (
<div>
<ScrollSync>
{({
clientHeight,
clientWidth,
onScroll,
scrollHeight,
scrollLeft,
scrollTop,
scrollWidth,
}) => {
return (
<div ...>
<AutoSizer>
{(childrenParam) => (
<div>
<div
<Grid
className={styles.HeaderGrid}
columnWidth={(index) => this._getColumnWidth(index, childrenParam.width - scrollbarSize())}
columnCount={columnCount}
height={rowHeight}
overscanColumnCount={overscanColumnCount}
cellRenderer={(headerParam) => this._renderHeaderCell(headerParam, childrenParam.width - scrollbarSize())}
rowHeight={rowHeight}
rowCount={1}
scrollLeft={scrollLeft}
width={childrenParam.width - scrollbarSize()}
/>
</div>
<div>
<Grid
cellRenderer={(headerParam) => this._renderBodyCell(headerParam, childrenParam.width - scrollbarSize())}
className={styles.BodyGrid}
columnWidth={(index) => this._getColumnWidth(index, childrenParam.width - scrollbarSize())}
columnCount={columnCount}
height={childrenParam.height}
onScroll={onScroll}
overscanColumnCount={overscanColumnCount}
overscanRowCount={overscanRowCount}
rowHeight={rowHeight}
rowCount={rowCount}
width={childrenParam.width}
/>
</div>
</div>
)}
</AutoSizer>
</div>
);
}}
</ScrollSync>
</div>
);
}
_renderBodyCell({columnIndex, key, rowIndex, style}, totalWidth) {
const rowRenderer = this.props.data[rowIndex];
return (
<div key={"body_" + key}>
{ rowRenderer.renderCell(columnIndex) }
</div>
);
}
_renderHeaderCell({columnIndex, key, rowIndex, style}, totalWidth) {
const headerData = this.props.headers[columnIndex];
return (
<div key={"header_" + key}>
{ headerData.name }
</div>
);
}
...
}
export class RowRenderer {
...
renderCell = (column) => {
switch (column) {
case 0 :
return (
<div>
{ this.data.propA }
</div>
);
case 1 :
return (
<div>
{ this.data.propB }
</div>
);
case 2 :
return (
<div>
{ this.data.propC }
</div>
);
...
};
}
Do you have any clue on why the grid is rendering its initial datas filtered on the n first rows an not the filtered datas its receives with props ?
Thank you.
Activity
[-]Problem resfreshing while filtering datas[/-][+]Problem refreshing while filtering datas[/+]pete-moss commentedon May 18, 2018
In our use, if our data changes, we sometimes have to call forceUpdate() on the Grid instance to make it re-render. I think there are some optimizations in the Grid code to minimize the calls to render(). Simply reducing the rowCount may not be enough to trigger a rerender. This is even worse if you are using variable-height rows where you may have to call Grid.recomputeGridSize() after a data change.
Anderson-James-oss commentedon May 24, 2018
How to use this scenario ? (forceUpdate())
I want to ask when to call forceUpdate() ? How to use it ?
I'm not going to use forceUpdate()
pete-moss commentedon May 24, 2018
In our component that wraps a MultiGrid (equivalent to your VirtTable), we added a dataFreshness: any prop. If you do that, the user of VirtTable would then change this value whenever the data changes. Then in the componentWillReceiveProps() lifecycle method, check to see if dataFreshness has changed. If so, call MultiGrid.forceUpdateGrids(). You will have to get a ref to the MultiGrid in order to call this method. That forces a rerender pass on all Grids contained by the MultiGrid. That should ensure that your new rows are rendered.
This technique works great when we are fetching new data and doing sorting and filtering since the rowCount may or may not change.
wuweiweiwu commentedon Jun 1, 2018
I would try to update to 9.19.x version of react virtualized. any prop changes should trigger a re-render.
however,
forceUpdateandforceUpdateGridsare also viable alternatives.hope that helps!
wuweiweiwu commentedon Jun 1, 2018
@koalajun I would recommend calling
forceUpdatewhen you data updates.ex:
kpennell commentedon Aug 16, 2018
Having similar problems with client side filtering. All of this has forced me to learn this api well. But yeah, still can't figure out how to update this.
kpennell commentedon Aug 17, 2018
@krayush thx for this. I'll give it a try.
priley86 commentedon Jun 21, 2019
Hi, I'm seeing a similar issue when data changes after I have set
isScrollingOptOut = true. My current workaround is to refresh the gridonComponentUpdate:https://github.com/openshift/console/blob/5107eacc97430f453dc9cf573d0f779dd5eea746/frontend/public/components/factory/table.tsx#L365
We've written a wrapper around
VirtualGriddue to changes proposed in #1377, however this is essentially the same: