0

My current React sample implementation looks something like:

var MyComponent = React.createClass({
    getInitialState: function () {
        return {x: []};
    },
    //..... Some stuff here

    render: function () {
        var x = this.state.x;
        var fx = messages.map(function (m, i) {
            return React.createElement(SomeChildComponent, {data: val1});
        });

        return (
                React.createElement('div', {}, fx));
    }
});

As you can see, it runs the map function and iterates over entire array everytime update method is called. Its like doing same thing over and over. Is there a way so that it only adds the ReactChildComponent to just the final array index. Something like:

var MyComponent = React.createClass({
    getInitialState: function () {
        return {x: []};
    },

    ComponentWillReceiveProps: function() {
        this.state.x.push(this.props.data);
    },

    render: function () {
        var x = this.state.x;
        var xl = x. length;

        x[xl - 1] =  React.createElement(SomeChildComponent, {prop1: val1, prop2: val2});

        return (
                React.createElement('div', {}, xl));
    }
});

So that I can just assign the value to array's final index just once and it just remains there so I don't have to iterate over array everytime. I tried this but somehow the ComponentWillReceiveProps never gets called and the array ends up being empty (hence selecting length-1 index breaking code).

Is there a neat way to implement this? Is this a good choice? Why do most people just reiterate over entire loop most of the time using map (as shown in first example).

Assuming my application must give me as much performance as I can achieve as its a real-time app, so I do not want to reiterate over array every time.

user3271166
  • 573
  • 1
  • 6
  • 17

1 Answers1

1

Best practice would be to iterate over the entire array every time. This ensures that the state is always accurately represented when the component is rendered. The map function should be relatively inexpensive as far as performance goes (unless you have tens or hundreds of thousands of items in the array).

The idea of React is that often the performance bottleneck of javascript applications happens when updating the DOM. Because React updates the DOM in a smart way (https://facebook.github.io/react/docs/reconciliation.html) it helps you avoid performance issues. The added benefit of this is that you don't need to keep track of adding and removing elements as your array changes. React will do that for you.

Let me know if you need further explanation/reasoning behind this. More to read here: https://facebook.github.io/react/docs/rendering-elements.html#react-only-updates-whats-necessary

Ben Nyberg
  • 952
  • 7
  • 13
  • Hello and thanks for the reply. This is actually a chating application's section that loads chats, so the previous components do not change, only the new ones are added. Also, say if I was not to implement lazy-loading and had to store all thousands of messages, what would be the solution then? – user3271166 Dec 01 '16 at 22:53
  • For the first question, when you load new items, I would suggest using this immutability helper: https://github.com/kolodny/immutability-helper. Rather than pushing to the array, this will create a new array each time, for example: `this.setState({ array: update(array, { $push: ['array','with','new','items'] }) })` Why do this? Because pushing to the array won't trigger React to render again, but setting a new array as state will. And despite what you might think, it's not really a performance or bad memory hit. – Ben Nyberg Dec 01 '16 at 23:07
  • For the second question, I would say you shouldn't allow this scenario. The user can only have so many chat items on their screen at once, and scrolling through 100,000 messages will be a performance hit no matter what. You should load the previous chats and as needed by the user, and remove when they are no longer relevant to what the user is looking at. My guess is even 10,000 messages will be fine, as long as you don't render them to the DOM when they are not within the visible area of your app. – Ben Nyberg Dec 01 '16 at 23:15
  • Thanks! I figured out the problem; it appears that I do not yet completely understand react lifecycle. When component is rendered for first time, somehow the `componentWillReceiveProps` isn't fired (hence the array remained blank). However, `componentWillMount` is fired. I just used this function and it filled in array with the props passed; and even rendered correctly. Although on research, it appears that `push` will trigger the render, however it might lead to race condition: http://stackoverflow.com/questions/26253351/correct-modification-of-state-arrays-in-reactjs So I will look there too – user3271166 Dec 01 '16 at 23:22