Author avatar

Vivek Kumar

Handling Consecutive Renders Where a List Shuffles

Vivek Kumar

  • Aug 9, 2019
  • 8 Min read
  • 7 Views
  • Aug 9, 2019
  • 8 Min read
  • 7 Views
Web Development
React

Introduction

When you are working in React, there is an enormous scope of making things work, one way or the other. There are so many libraries and props that you can actually experiment with your work to get suitable outcomes, according to your requirements. The rendering process is one such component. The process of quality rendering takes time and, if the transition is demanding, then there might be a requirement of consecutive renders.

The creation of a list with common features and components can be accomplished with the help of basic animation. Here, the results can even be achieved with a single rendering. But the whole game changes when we add typical characteristics like the simultaneous shuffling of the list. In one such case, we create a list shuffling randomly with the help of certain animation. Now, in order to attain this in a high-quality environment, you are going to be required to proceed with consecutive renders.

In this guide, our sole objective is going to learn what happens on consecutive renders where a list shuffles. What are the limitations and challenges that usually arise and how can one overcome them? Once you have finished with this guide, you are going to be ready to hone your skills in one more aspect of React in the form of list shuffling animation and acquiring quality outcomes with consecutive renders.`

The List with Random Shuffling and Standard Approach

Now, when we are creating a list with the random shuffling, we generally use the following commands in order to apply the key prop to recognize each child.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
var ListAnimate = React.createClass({
    list: [
        {id: 1, caption: "One"},
        {id: 2, caption: "Two"},
        {id: 3, caption: "Three"},
        {id: 4, caption: "Four"},
        {id: 5, caption: "Five"},
    ],
    shuffle: function() {
        this.list.shuffle(); // Shuffles array!
        this.forceUpdate();
    },
    render: function() {
        return <div>
            <button onClick={this.shuffle}> Shuffle </button>
            <ul>
                {this.list.map(function(el, i){
                    return <li key={el.id} style={ {top: (i*60)+'px'} }>{el.caption} {el.id}</li>;
                })}
            </ul>
        </div>;
    }
});

React.render(<ListAnimate />, document.body);
javascript

The example demonstrated above has used fictional names and classes to help you visualize the basic situation that we are talking about right now. From React docs, it states that the application of the key props should be done in order to recognize each element in an array in the process of successive renders. The process is basically done in order to ensure that items that are just reordered, should not unmount and then mount to a relatively new position. Instead of that, they should simply reposition right at the top of the list without actually getting unmounted and then get mounted on a whole new position.

Now, when you encounter one such condition, you are going to find that the elements that are operating at the bottom are working precisely well with the animation. It is usually the elements at the top that, generally, create the problem. I am saying this because, in the past, this is the problem which was faced by many people.

The Correct Approach

Now the glitch that has been highlighted above is experienced by most of us. There is a simple, yet highly reliable, solution to the problem - which you are required to keep in mind going for consecutive renders. Here, in order to acquire the concerned kind of animation, it is recommended to always keep Document Object Model (DOM) in the identical order and update their concerned position in the render function associated with your concerned component. Once you accomplish this, the render is going to look like the following:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
render: function() {
    // create a sorted version of the list to render the DOM
    var sortedCopy = this.state.list.slice().sort(function(a, b) {
        return a.id - b.id;
    });

    return <div>
        <button onClick={this.shuffle}> Shuffle </button>
        <ul>
            {sortedCopy.map(function(el, i) {
                // find the position of the element in the shuffled list
                // which gives the position the element must be
                var pos = this.state.list.indexOf(el);
                return <li key={el.id} style={ {top: (pos*60)+'px'} }>
                    {el.caption} {el.id}
                </li>;
            }, this)}
        </ul>
    </div>;
}
javascript

The solution that has been mentioned above does come with the scope of improvement, yet it can work for you in React pretty well and offer you stable results.

An Alternative Approach

There is an alternative way of doing things in which the component that has been mounted is going to be called during the first render. After that, none of the elements are going to be called once the shuffling is done.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
var MyLi = React.createClass({
    componentDidMount : function(){
        console.log("MyLi component did mount.");
    },

    componentWillUnmount : function(){
        console.log("MyLi component will unmount.");
    },

    render : function(){
        return <li {...this.props}>{this.props.children}</li>
    }
});

var ListAnimate = React.createClass({
    list: [
        {id: 1, caption: "One"},
        {id: 2, caption: "Two"},
        {id: 3, caption: "Three"},
        {id: 4, caption: "Four"},
        {id: 5, caption: "Five"},
    ],
    shuffle: function() {
        this.list.shuffle();
        this.forceUpdate();
    },
    render: function() {
        return <div>
            <button onClick={this.shuffle}>Shuffle</button>
            <ul>
                {this.list.map(function(el, i){
                    return <MyLi key={el.id} style={ {top: (i*60)+'px'} }>{el.caption} {el.id}</MyLi>;
                })}
            </ul>
        </div>;
    }
});
window.React = React; 
React.render(<ListAnimate />, document.body);

Array.prototype.shuffle = function() {
  var i = this.length, j, temp;
  if ( i == 0 ) return this;
  while ( --i ) {
     j = Math.floor( Math.random() * ( i + 1 ) );
     temp = this[i];
     this[i] = this[j];
     this[j] = temp;
  }
  return this;
}
javascript

In this approach, the conversion of li element has been done to MyLi element as well as the logged messages when the componentDidMount and componentWillUnmount functions are called.

Conclusion

With the end of this guide, I believe that the next time that you encounter a situation with consecutive renders where a list shuffles, you are going to be well prepared. In this guide, we have discussed the dummy case of list reshuffling and what can be the standard approach of dealing with the same. What are the general loopholes that you can encounter during the course of the process and what are the countermeasures that you can wield to get things done, as per your convenience? The alternative approach suggested in this guide is also going to help you in special cases.

So go ahead and proceed with another successful list shuffling animation in React. The problems that frequently encountered with consecutive renders are not going to bother you anymore.

Reference

You can further refer the following resource which is also used as a reference for this guide:

0