React Table Virtualization
Example that shows you how to apply this technique to a table.
HTML
<script src="https://unpkg.com/react@16.2.0/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16.2.0/umd/react-dom.development.js"></script>
<script src="https://unpkg.com/prop-types/prop-types.js"></script>
<div id='app'></div>
CSS
.wrapper {
display: inline-block;
}
.wrapper table {
border-style: none;
/*border-collapse: collapse;*/
/*display: block;*/
}
.table-content {
overflow-y: scroll;
border-collapse: collapse;
display: block;
}
th {
background-color: #333;
color: #fcfcfc;
}
td {
color: #333;
}
th, td {
text-align: center;
font-size: .6rem;
font-weight: bold;
text-transform: uppercase;
font-family: sans-serif;
width: 6rem;
}
.tr {
height: 35px;
max-height: 35px;
}
.tr-odd {
background-color: #DADDE1;
}
.tr-even {
background-color: #fcfcfc;
}
Babel + JSX
const { Component } = React
const { render, findDOMNode } = ReactDOM
class Table extends Component {
constructor(props) {
// Initial props:
super(props)
// Initial state:
this.state = {
columns: Object.keys(this.props.rows[0]),
tableHeight: (this.props.rowHeight * this.props.rows.length),
scroll: {
top: 0,
index: 0,
end: Math.ceil((this.props.tableHeight * 2) / this.props.rowHeight)
}
}
// Event handlers:
this.onScroll = this.onScroll.bind(this)
this.scrollInterval = null
}
onScroll({ target }) {
let state = this.state;
let scrollTop = target.scrollTop
let rowHeight = this.props.rowHeight
let tableHeight = this.props.tableHeight
let index = Math.floor(scrollTop / rowHeight)
state.scroll.index = index
state.scroll.end = index + Math.ceil((tableHeight * 2) / rowHeight)
state.scroll.top = (scrollTop / rowHeight) * rowHeight
this.setState(state);
}
generateRows() {
let columns = this.state.columns
let rowHeight = this.props.rowHeight
let rows = this.props.rows
let index = this.state.scroll.index
let end = this.state.scroll.end
let items = []
do {
if (index >= rows.length) {
index = rows.length
break
}
const rowAttrs = {
style: {
position: "absolute",
top: (index * rowHeight),
left: 0,
height: rowHeight,
lineHeight: `${rowHeight}px`
},
className: `tr ${(index % 2) === 0 ? 'tr-odd' : 'tr-even'}`
}
items.push(
<tr {...rowAttrs} key={index}>
{columns.map((column, i) =>
<td key={i}>
{rows[index][column]}
</td>
)}
</tr>
)
index++
} while (index < end)
return items
}
render() {
const tableHeight = (this.props.tableHeight > this.state.tableHeight)
? this.state.tableHeight + 2
:...