angularjs - learning - reactjs vs angular 2




React vs Angular: Slow rendering with React (4)

I'm surprised nobody mentioned PureRenderMixin . It implements shouldComponentUpdate so you don't have to worry about it.

Also, I wonder if React Performance Tools would turn up something useful?

And I'm surprised to hear Angular is faster than React after watching this talk from Ryan Florence .

I was doing a comparison of Angular and React and decided to try out a performance test to see how fast a large(ish) list would render in both frameworks.

When I got done with my React prototype with some basic currency formating, it was taking ~2 seconds to render on my fast laptop. With Angular it was barely noticeable -- only when I switched to my phone did it have a noticeable lag.

This was very surprising because I was told that React was supposed to beat the pants off of Angular for performance, but it appears that the opposite is true in this case.

I distilled my prototype down to a very simple app to try to isolate the issue: https://github.com/pselden/react-render-test

In this sample, it's taking almost 200ms to render this simple list after changing the language, and I'm barely doing anything.

Am I doing something wrong here?

/** @jsx React.DOM */
'use strict';

var React = require('react'),
    Numbers = require('./Numbers');

var numbers = []
for(var i = 0; i < 2000; ++i){
    numbers.push(i);
}

var App = React.createClass({
    getInitialState: function() {
        return { locale: 'en-US' };
    },

    _onChangeLocale: function(event) {
        this.setState({locale: event.target.value});
    },

    render: function() {
        var currentLocale = this.state.locale;

        return (
            <div>
                <select
                    onChange={this._onChangeLocale}>
                    <option value="en-US">English</option>
                    <option value="fr-FR">French</option>
                </select>
                <Numbers numbers={numbers} locales={[currentLocale]} />
            </div>
        );
    }
});

module.exports = App;
/** @jsx React.DOM */
'use strict';

var React = require('react'),
    ReactIntlMixin = require('react-intl');

var Numbers = React.createClass({
    mixins: [ReactIntlMixin],

    getInitialState: function() {
        return {
            numbers: this.props.numbers
        };
    },

    render: function() {
        var self = this;
        var list = this.state.numbers.map(function(number){
            return <li key={number}>{number} - {self.formatNumber(number, {style: 'currency', currency: 'USD'})}</li>
        });

        return <ul>{list}</ul>;
    }
});

module.exports = Numbers;

PS: Added an angular version: https://github.com/pselden/angular-render-test

Edit: I opened an issue with react-intl and we investigated and found that there was not that much overhead with using https://github.com/yahoo/react-intl/issues/27 -- it's simply React itself that is slower here.


In React component, once you call setState, it will trigger the render function immediately. React will mark this component as dirty, and will re-render all the children element inside this component.

It will not render the whole Native DOM elements because of the Virtual DOM, thus it will still create new instances of its children ReactElements, which can lead to extra Javascript memory cost.

To avoid this issue, you need shouldComponentUpdate function which implemented in Component Class. it will executed before Render method. If you find the there is nothing changed right now, for instance in your example, you change the state.locale. You can definitely consider this component need no update. so just return false to prevent the render call.

This is a base solution to solve React performance issues. Try to add "shoudlComponentUpdate" in your Numbers Component to avoid tons of

  • element re-render


  • This is an example where all that is changing is one data output. It's not impossible that Angular's two way data-binding simply offers a faster re-render when all that is changing is the display of the bound data.

    React does not promise that its renders are faster than any other framework under all circumstances. What it does offer is the ability to handle ~arbitrarily complex DOM updates in very efficient manner, and offer a variety of lifecycle methods (e.g. componentWillReceiveProps, componentDidUpdate, in addition to the afore-mentioned shouldComponentUpdate) to let you fire callbacks on those events and control how and if they should happen. Here, there's very little to optimize, because all you are doing is changing 2,000 text displays.

    edit: To clarify, React is useful in doing more complex DOM manipulations because it's virtual DOM algorithm allows it to choose the minimal set of DOM operations necessary to update your DOM. That's still a lot of work to do when all that needs to be happening is 2000 instances of some text changing.


    This is definitely an interesting test case.

    If you take a look at the timelines, you can see that Angular is finished handling the change event in a mere 20ms. The remainder of the time is spent in layout and repaint.

    React (using a production build, your repo uses dev by default) takes about 59ms. Again, the rest of the time is spent in layout and repaint.

    If you take a look at the CPU flame charts, you can see that Angular appears to be doing a lot less work.

    Angular:

    React:

    React provides a pretty good optimization hook in the form of shouldComponentUpdate that is especially useful when a single instance of a component out of thousands should update and the others should stay the same; it's a technique I use in this demo (try it out in an incognito window; I've found some Chrome extensions make layout/repaint times much higher—for me, adding/removing single elements once the list is 1000 long takes ~13ms, changing the size/color of an element takes ~1ms). However, it does no good when every element needs to update.

    My guess is that Angular will be faster at changing most or all of the elements in your table, and React will be quite proficient at updating select entries when using shouldComponentUpdate .







    reactjs