Components with large datasets runs slow on IE11/Edge only

13,469

Solution 1

Things to try improve IE performance:

  • check you are running in production mode (which removes things like prop validation) and make Webpack / Babel optimisations where applicable

  • Render the page server side so IE has no issues (if you can support SS rendering in your setup)

  • Make sure render isnt called alot of times, tools like this are helpful: https://github.com/garbles/why-did-you-update

  • Any reason why you are using dangerouslySetInnerHTML? If you take out the dangerouslySetInnerHTML does it speed things up dramatically? Why not just automatically generate the rows and cols based on a array of objects (or multidimensional array passed), im pretty sure then React will make less DOM interaction this way (makes use of the VDOM). The <tr> and <td>'s will be virtual dom nodes.

  • Use something like https://github.com/bvaughn/react-virtualized to efficiently render large lists

Solution 2

Shot in the dark: try not rendering, or not displaying, until everything is completely done.

  • make the table element display:none until it's done
  • render it offscreen
  • in a tiny DIV with hidden overflow
  • or even output to a giant HTML string and then insert that into the DOM upon completion.
Share:
13,469
Perfection
Author by

Perfection

{}, {}'s EVERYWHERE.

Updated on July 02, 2022

Comments

  • Perfection
    Perfection almost 2 years

    Consider the code below. <GridBody Rows={rows} /> and imagine that rows.length would amount to any value 2000 or more with each array has about 8 columns in this example. I use a more expanded version of this code to render a part of a table that has been bottle necking my web application.

    var GridBody = React.createClass({
        render: function () { 
            return <tbody>
                {this.props.Rows.map((row, rowKey) => {
                        return this.renderRow(row, rowKey);
                })}
            </tbody>;
        },
        renderRow: function (row, rowKey) {
            return <tr key={rowKey}>
                {row.map((col, colKey) => {
                    return this.renderColumn(col, colKey);
                })}
            </tr>;
        },
        renderColumn: function (col, colKey) {
            return <td key={colKey} dangerouslySetInnerHTML={{ __html: col } }></td>;
        }
    });
    

    Now onto the actual problem. It would seem that computation (even with my own code) seems to be suprisingly fast and even ReactJS's work with the virtualDOM has no issues.

    But then there are these two events in reactJS.

    componentWillUpdate up until where everything is still okay. And then there is componentDidUpdate which seems to be fine and all on chrome.

    The problem

    But then there is IE11/Edge with about 4-6 SECONDS slower than any other browser and with the F12-Inspector this seems to be p to 8 SECONDS slower than Chrome.

    The steps I have done to try and fix this issue:

    • Strip unnecessary code.

    • Shave off a handful of milliseconds in computation time.

    • Split the grid in loose components so that the virtualDOM doesn't try to update the entire component at once.

    • Attempt to concaternate everything as a string and allow react to only set innerhtml once. This actually seems to be a bug in IE here a large string takes about 25-30 seconds on IE11. And only 30 ms on chrome.

    I have not found a proper solution yet. The actions I have done above seemed to make things less bad in IE but the problem still persists that a "modern" or "recent" browser is still 3-4 seconds slower.

    Even worse, this seems to nearly freeze the entire browser and it's rendering.

    tl;dr How to improve overal performance in IE and if possible other browsers?

    I apologize if my question is unclear, I am burned out on this matter.

    edit: Specifically DOM access is slow on IE as set innerHTML gets called more than 10.000 times. Can this be prevented in ReactJS?

  • Perfection
    Perfection almost 8 years
    react-virtualized uses the same ideas as several implementations that we've made ourselves and it also has the same performance issues that we're seeing in browsers like IE10-11. DangerouslySetInnerHTML is used to set some HTML that we're getting from our resultset. We have tried without this and didn't give us any difference from our tests. Also server side rendering is already enabled but comes with the same issues when a rerender happens.
  • Perfection
    Perfection almost 8 years
    I checked with a github fork but we've already thoroughly fought off most unwanted rerenders. But that's not particularly the issue here. When the component has to rerender a new data set (i.e. a newly ordered dataset is pushed) then the browser has a very hard time to keep up with finding the dom node and setting innerhtml. In our code's current state the re-render only happens once.
  • Perfection
    Perfection almost 8 years
    I'm not interrested in registering for more spam, sorry. And this would only help me find the problem that I have already found but provide no solution.
  • hazardous
    hazardous almost 8 years
    Your call. It's unfortunate telerik put an excellent tool behind mail wall.
  • Marty
    Marty almost 8 years
    have you tried to remove dangerouslySetInnerHTML just for testing the performance against IE? You said "We have tried without this and didn't give us any difference from our tests." does this mean you removed it as a temporary measure or you replaced it with <tr> and <td>'s?
  • Perfection
    Perfection almost 8 years
    Our tests are worst case senarios in our current code on Chrome, Firefox, IE Edge, IE11 + IE10 in emulated. It means we removed dangerouslySetInnerHTML and placed {col} between the '<td>' We measure the results in miliseconds determined by the browser.
  • Marty
    Marty almost 8 years
    Other thing you can double check is if it's in production mode and you have made other optimisations like removal of prop validation with Babel plugins
  • Perfection
    Perfection almost 8 years
    Rendering it off screen, setting the table element to display: none won't gain performance because the DOM search and manipulation still has to happen. We've tried putting it in an iframe to no avail. Already attempted to output as a giant html string and that is actually 3-8 times slower than 12000+ dom manipulations.
  • Perfection
    Perfection almost 8 years
    Hey, thanks Marty. Infact this helped us a lot. The difference between production and development mode was a literal performance gain of 40-50%. We didn't even think of that. This is a major non-intrusive step towards the way to go. You should add that to your answer so I can accept it.
  • Perfection
    Perfection almost 8 years
    Actually concaternating the html to a string and then doing a single DOM manipulation is much faster. For some reason IE is extremely slow with for() loops and arrays. Hence upvote.