I'm using Grid component and now I'm trying to implement hover effect for columns in Grid. Every time I hover some cell, I'll call custom method and set the state:
this.setState({
highlightedColumn: columnIndex,
});
This is working. But depends on this state in highlightedColumn I want to set custom class to rendered cells. I'm using _renderCell method:
_renderCell({ columnIndex, rowIndex }) {
var cellClasses = classNames({
'GridCell': true,
'GridCell--odd-row': rowIndex % 2 === 0,
'GridCell--highlighted': this.state.highlightedColumn === columnIndex,
});
return (
<div className={cellClasses}>
... CELL CONTENT ...
</div>
);
},
Problem is that class doesn't update. RenderCell is called only when I scroll with the Grid. Is there any chance to re-render Grid also when I update state of component?
Tried using the React forceUpdate method? I think the docs mention this somewhere but... I don't recall. :)
I'm going to close this issue since it's just a question and _I think_ I've actually answered it. But if not, we can keep chatting on the issue. I don't mind. I just don't like leaving non-actionable issues open.
forceUpdate doesn't work in this case. This is our example for big datatable with many columns and fixed header:
_renderTableCell({ columnIndex, rowIndex }) {
var cellClasses = classNames({
'GridCell': true,
'GridCell--odd-row': rowIndex % 2 === 1,
'GridCell--highlighted': this.state.highlightedColumn === columnIndex,
});
return (
<div className={cellClasses}>
SOME CONTENT HERE
</div>
);
},
...
<ScrollSync>
{({ clientHeight, clientWidth, onScroll, scrollHeight, scrollLeft, scrollTop, scrollWidth }) => {
return (
<div>
<div style={{
position: 'relative',
height: headerHeight,
width: tableWidth - scrollbarSize(),
}}>
<Grid
className={'HeaderGrid'}
columnWidth={this._getColumnWidth}
columnsCount={5}
height={headerHeight}
onScroll={onScroll}
renderCell={this._renderHeaderCell}
rowHeight={headerHeight}
rowsCount={1}
scrollLeft={scrollLeft}
width={tableWidth - scrollbarSize()}
/>
</div>
<div
style={{
height: tableHeight - headerHeight,
width: tableWidth,
}}
>
<Grid
width={tableWidth}
height={tableHeight - headerHeight}
columnWidth={this._getColumnWidth}
rowHeight={this._getRowHeight}
columnsCount={5}
onScroll={onScroll}
rowsCount={pagesCount}
renderCell={this._renderTableCell}
scrollLeft={scrollLeft}
/>
</div>
</div>
);
}}
</ScrollSync>
When called forceUpdate I checked that <Grid> itself is re-rendered, but I expected also calling of this._renderTableCell again. This didn't happen. I set classes for each cell in this._renderTableCell. Is there any different way how to re-render cells? Cell is re-rendered only when I scroll with Grid content.
Thanks
Works for me? (live demo, source code)

Thanks. Your example help us to solve it. Problem was that I was trying to target Grid directly by this.refs.Grid. This syntax this.refs.AutoSizer.refs.Grid is right in this case.
Ah, glad to hear it :)
On Thursday, March 31, 2016, Martin Pešout [email protected] wrote:
Thanks. Your example help us to solve it. Problem was that I was trying to
target Grid directly by this.refs.Grid. This syntax
this.refs.AutoSizer.refs.Grid is right in this case.—
You are receiving this because you modified the open/close state.
Reply to this email directly or view it on GitHub
https://github.com/bvaughn/react-virtualized/issues/167#issuecomment-203808217
Hello,
I have the same problem. Cell is re-rendered only when I scroll with Grid content.
Can you help me please?
class StatisticsGrid extends MultiGrid {
_getLeftGridWidth(props) {
return 300;
}
}
export default class Table extends React.Component {
constructor(props) {
super(props);
this.state = {
loading: true,
hoveredColumnIndex: "",
hoveredRowIndex: "",
};
this._cellRenderer = this._cellRenderer.bind(this);
}`
<div className="multiGridWrapp">
<StatisticsGrid
{...this.props.appState.data}
ref="Grid"
cellRenderer={this._cellRenderer}
columnWidth={40}
columnCount={this.props.appState.data.period.length}
enableFixedColumnScroll
enableFixedRowScroll
fixedColumnCount={1}
fixedRowCount={1}
height={500}
rowHeight={60}
rowCount={this.props.appState.data.values.length}
style={STYLE}
styleBottomLeftGrid={STYLE_BOTTOM_LEFT_GRID}
styleTopLeftGrid={STYLE_TOP_LEFT_GRID}
styleTopRightGrid={STYLE_TOP_RIGHT_GRID}
width={1198}
hideTopRightGridScrollbar
hideBottomLeftGridScrollba
/>
</div>
</React.Fragment>);
_cellRenderer({columnIndex, key, rowIndex, style}) {
let setState = this.setState.bind(this);
let className =
columnIndex === this.state.hoveredColumnIndex ||
rowIndex === this.state.hoveredRowIndex
? 'hoveredCell'
: '';
let grid = this.refs.Grid;
// {columnIndex} {rowIndex}
let customClass = "cellFirst";
if (columnIndex != 0 && rowIndex == 0)
customClass = "cellHeader";
else if (columnIndex == 0 && rowIndex != 0)
customClass = "cellRules";
else if (columnIndex != 0 && rowIndex != 0)
customClass = "cell";
customClass += rowIndex%2===1 ? " odd":"";
return (
<div onClick={() => { alert("as "); }} onMouseOver={() => { setState({ hoveredColumnIndex: columnIndex, hoveredRowIndex: rowIndex, }); grid.forceUpdate();}} className={customClass + " "+className} key={key} style={style}>
{columnIndex != 0 && rowIndex == 0 && this.props.appState.data.period[columnIndex].split('-').map(function (data, index) {
return (<span key={index}>{data}</span>);
})}
{columnIndex == 0 && rowIndex != 0 && this.props.appState.data.values.length>0 ? <span>{"ID: "}<b>{this.props.appState.data.values[rowIndex - 1].id} </b>{" - "}{this.props.appState.data.values[rowIndex - 1].name}<span>{this.props.appState.data.values[rowIndex - 1].subject}</span></span>: null}
{columnIndex != 0 && rowIndex != 0 && this.props.appState.data.values.length>0 && this.props.appState.data.values[rowIndex - 1].data[this.props.appState.data.period[columnIndex]]}
</div>
);
}
}`
I tried to add let grid = this.refs.Grid; what i saw in your example but only what is changing are the cells in header.
Thanks for your help!
@bvaughn
Done, I solved the problem.
this.refs.Grid shloud be grid.forceUpdateGrids() it's work now fine..
Most helpful comment
Works for me? (live demo, source code)