React.js and the big table

I need to draw a large table, not very large, about 400x400 cells. But React makes it too slow, and each time you click on a cell, the cell should be updated, and this update takes an equally huge amount of time. Any suggestions how to speed it up? Or is React just not the right tool for such a task?

Here is an example (with slightly reduced table size): 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')); 
+5
source share
3 answers

By default, React re-displays everything, but if there are performance issues, you can use the shouldComponentUpdate function to determine which parts of the component tree to exclude updates.

In your example, there is only one row that can be updated immediately, so if we start to track which row has occurred, we can make sure that only this row is updated. First, we must introduce a new component, which is 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 as

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

In addition, it seems that the waste also revises all of these cells, so we can introduce 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 significant performance improvements with updates. If it is not good enough for your specific problem, it is possible that React is not ideal for your use case. In any case, this is the essence of optimizing React programs, you break components into smaller components and make sure that only the parts that actually changed the update.

+2
source

While I was looking at your results in the console, I noticed that the following appeared on every jsfiddle run:

You are using the in-browser JSX transformer. Be sure to precompile your JSX for production - http://facebook.imtqy.com/react/docs/tooling-integration.html#jsx

I followed the link and saw that the documentation warns of a performance impact when using the built-in JSX translator:

The in-browser JSX transformer is fairly large and results in extraneous computation client-side that can be avoided. Do not use it in production

Perhaps another test with JSX precompilation will give you a better idea of ​​whether this is a good option for React.

0
source

Two things:

Be sure to precompile JSX to avoid this sluggishness. (In jsfiddle, you will see a console warning "You are using the built-in JSX translator. Be sure to precompile JSX for production."

Being implemented as one component with the condition for setting the click on its own, causes the component to process the entire table (because setState calls render , which rebuilds the DOM table). You can avoid this by creating a component to represent each cell in the table. Then in your clicked function clicked instead of calling setState on Hello just call setState in the cell the button was clicked on. Thus, only the changed cell will change.

This does not help the initial rendering, but will significantly speed up user interface updates due to clicks.

0
source

All Articles