Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React.js and big table

I need to draw a big table, not really big, about 400x400 cells. But React renders it too slow, and on every click on the cell, cell should be updated and this update takes same huge amount of time. Any suggestions how to speed it up ? Or React is just not suitable tool for such task ?

Here is example (with slightly reduced size of table): https://jsfiddle.net/69z2wepo/15731/

var ROWSC = 400;
var COLSC = 100;

var Hello = React.createClass({
    getInitialState: function () {
        return {
            t: { "1-1": 'c' }
        };
    },
    clicked: function (k) {
        var t = this.state.t;
        t[k] = t[k] ? 0 : 'c';
        this.setState({  t: t  });
    },
    render: function() {
        var items = [];
        for (var r = 0; r < ROWSC; r++) {
            var cols = [];
            for (var c = 0; c < COLSC; c++) {
                var k  = ''+r+'-'+c;
                cols.push(<td key={c} onClick={this.clicked.bind(this,k)} className={this.state.t[k]}>&nbsp;</td>);
            }
            items.push(<tr key={r}>{cols}</tr>);
        }
        return <table>
            {items}
            </table>
        </div>;
    }
});

React.render(<Hello name="World" />, document.getElementById('container'));
like image 257
Dfr Avatar asked Oct 30 '22 19:10

Dfr


1 Answers

By default, React re-renders everything, but in the presence of performance problems, it is possible to use the shouldComponentUpdate function to determine which parts of the component tree to exclude on updates.

In your example, there is only a single row that can be updated at once, so if we start tracking which row the update occured on we can make sure only this row is updated. First, we must introduce a new component that wraps the table row where we can place our hook.

var Row = React.createClass({
    shouldComponentUpdate: function(nextProps) {
        return nextProps.mustUpdate;
    },
    render: function() {
        return <tr>{this.props.children}</tr>;
    }
});

Then we can use it like

items.push(
   <Row key={r}
        mustUpdate={this.state.lastUpdatedRow === r}>
        {cols}
   </Row>);

Furthermore, it seems like a waste to re-render all those cells too, so we can introduce yet another component that wraps the table cells.

var Cell = React.createClass({
    shouldComponentUpdate: function(nextProps) {
        return this.props.selected !== nextProps.selected;
    },
    render: function() {
        var props = this.props;
        return (
            <td onClick={props.onClick.bind(null, props.col, props.row)} 
                className={props.selected ? 'c' : ''}>&nbsp;
            </td>
        );
    }
});

This should give you a significant performance improvement on updates. If it is still not good enough for your particular problem, it might be that React is not ideal for your use case. Anyway, that is the essence of optimizing React programs, you split components into smaller components and make sure only the parts that actually changed update.

like image 167
Heap Avatar answered Nov 08 '22 10:11

Heap