Optimize Performance in react-beautiful-dnd with shouldComponentUpdate and PureComponent

Alex Reardon
InstructorAlex Reardon

Share this video with your friends

Send Tweet
Published 4 years ago
Updated a year ago

We will look at allowing style updates to Draggable and Droppable components without re-rendering their children. We will do this by creating a new component <InnerList /> which conditionally block renders with React's shouldComponentUpdate lifecycle hook.

After this, you'll see how using React's PureComponent can be used to achieve the same optimization.

Instructor: [00:00] In this lesson, I will be talking about some important performance optimizations that you can implement to make your application as fast as possible.

[00:10] A big performance bottleneck in React is the reconciliation process. In short, you do not want to be calling the render function on components that do not need to have any changes applied. I am going to be using the React Developer Tools extension for Chrome, which is available through the Chrome Web Store.

[00:30] The extension has an incredibly useful toggle called highlight updates. By enabling this feature, the dev tool will highlight the components in our React application that have hand their render function called.

[00:50] I'm going to change the dragging of a background color of our column from sky blue to light gray for this lesson. I'm going to do this so we can more clearly see what's going on.

[01:03] When I pick up a task, you will see that all of the tasks have been highlighted in blue. This shows that the component has had its render function called. When the droppable inside of our column calls its child function, it is going to render out all of its tasks.

[01:25] A droppable function will be called whenever the value of the snapshot argument changes. This will occur whenever you enter or leave a droppable. You can see, as I'm entering and leaving, all of the tasks in the list are having a blue outline applied to them, indicating that their render method is being called.

[01:50] We want our task list to respond to snapshot value changes, as we want to update its background color in response to a drag. However, we don't want to render out all of the tasks in order to make this style change. I'm going to replace this map here with a new component.

[02:21] We have moved the logic for mapping over the tasks and returning a task component into this inner list component. I'm now adding a shouldComponentUpdate lifecycle method.

[02:33] We're going to skip a render if the new tasks array shares referential equality with the existing tasks array. If the reference to the array has changed, then we will allow a render. Now when we drag a task, we are able to update the background color of the task list, but we do not need to render the task components that did not need to be rendered.

[03:05] When I drag a column, all the tasks in the column render. You can see that all of the tasks are having a blue outline applied to them to indicate that they are being rendered.

[03:17] Here is the droppable for our columns. When I drag a column, all of the tasks in the column render. This is because our droppable function is being called with a new snapshot value even though we're not using it right now.

[03:44] When this droppable function is called, it is going to return a new list of column components. Just as with our column component, we want to avoid the rendering of the children of our droppable, which in this case is container, during a drag.

[04:09] Rather than returning a column component, we're now going to return a new inner list component that is responsible for rendering a column. The key difference to the interface is that rather than passing in a dynamically created tasks array, we are passing in the entire tasks object map.

[04:41] The inner list component is performing the same operations as we were previously doing inside of our droppable function. If we were to leave it here, we wouldn't have any performance wins.

[04:58] We can now conditionally block renders if none of the props have changed. The key change that has enabled us to make this optimization is to pass in the entire task map, rather than a dynamically created tasks array. None of these three properties should change during a drag.

[05:21] This change would allow us to add styles to our column while it was dragging, while still avoiding the rendering of our children. We can change our component to instead extend from pure component. A pure component performs the same shouldComponentUpdate check as what we have here.

[05:47] Now when we drag our column, we will see that the tasks are no longer being highlighted in blue, showing that they are no longer being rendered.