译 文 : Beautiful and Accessible Drag and Drop with react-beautiful- DND
The original text is video course, I just translate and organize the porter ^_^.
React-beautiful-dnd drag-and-drop with elegance and ease
What is react-beautiful-DND and what are we going to use to build projects
React Beautiful DND allows elegant and easy list drag-and-drop effects with React. My name is Alex and I’m the author of React Beautiful DND. In this class, I will take you hand in hand to implement a highly interactive task management application.
I’ll introduce the React Beautiful DND module and you’ll learn how to use it to add powerful drag-and-drop effects to your projects. The following projects support task reordering, moving tasks between lists, moving with conditions, and reordering lists.
All effects are available on desktop and mobile, but also for users who just want to experience the full effects with keyboard and screen reading.
Create the React environment with create-react-app
In this class, we will usecreate react app
Create the following projectReact
The environment
Code: codesandbox. IO/embed/githu…
To start exploring react-beautiful-DND, we need to create the React development environment. An easy way to do this is to use create-react-app, which can be used directly from NPM:
npx create-react-app task-app
Copy the code
Running the command line, we create a new React project in the task-app folder.
Now that the installation is complete, we can move to the task-app folder and run YARN Start to start the development server. We can see the project at localhost:3000.
We have index.js created with create-react-app to remove unnecessary files and content, and now have an empty React development environment for developing projects.
React creates lists of data and adds styles
(I recommend that you open the code first and read the tutorial to understand the implementation.)
In this lesson we will create and explain task lists from scratch. This lesson creates the state model and components that we use to build our task list. We will implement drag-and-drop effects based on lists
Code: codesandbox. IO/embed/githu…
We will sort the project data. React-beautiful-dnd doesn’t care how you structure or manage your data. For our purposes, we use a simple data structure.
const initialData = {
tasks: {
'task-1': { id: 'task-1'.content: 'Take out the garbage' },
'task-2': { id: 'task-2'.content: 'Watch my favorite show' },
'task-3': { id: 'task-3'.content: 'Charge my phone' },
'task-4': { id: 'task-4'.content: 'Cook dinner'}},columns: {
'column-1': {
id: 'column-1'.title: 'To do'.taskIds: ['task-1'.'task-2'.'task-3'.'task-4'],}},// Facilitate reordering of the columns
columnOrder: ['column-1']};export default initialData;
Copy the code
The first data attribute is Tasks. The Tasks object owns the tasks for our system. It uses the id of the task as the key to query the task object. A task has an ID and its content is “Take out the garbage.”.
There is also the Column object, which holds the columns in the project. We use ID as the key to query the column. It’s our to-do list.
Each column has an array of task ids that exist for two purposes. The first is the designation of ownership. We know that Task-1 is in Column-1. The second is to use arrays to maintain order. Now task-1 precedes Task-2.
We also added another property called columnOrder. It is used to record the order of columns. Right now, we only have one column, and we can add more columns later.
We need to export the data and return index.js. In index.js, we can import the initial data, which is the basis of our rendering application. We set the initial state to the initial data, and the applied responsibility is to render the column:
The columnOrder array holds the order of the columns we want to render, taking the columns out of the state and rendering our columns. We will also take out the tasks associated with the column.
To make sure everything is correct, I return the column title in the project. Ok, no problem. We can see that the only column heading to-do is rendered.
We will render columns, not just titles. We need to give a key because we’re rendering a list of components and React uses a key to track. And the tasks in the column.
We need to create the column component to render. First, I’ll import the column component… But it doesn’t exist yet, so we’re going to create it. For our column component, we have to render the title again. Ok, good.
Our new column component renders column headers, and we’ll also start adding styles to our project. For this I use a library called Styled – Components, which is my favorite component-STYLE CSS in JS library.
React-beautiful-dnd has no comment on the style method you want to use. Whether it’s preprocessing styles like Less, Sass, Css in JS, inline styles, or any other style mechanism, take your pick.
I also added CSS reset to keep the visual consistency between different browsers. You can use your own CSS reset or not. Go back to index.js and import the reset file. You can see that our project looks a bit different.
Back in the column, import Styled from gravitation-Components, and we can create elements with styles. We need a container to wrap the elements around, and we’ll use div to do that.
We’re going to have a title, and we’re going to do that with H3. We will have the task list component, which is used to render our tasks. For the moment, we’ll use divs as placeholders.
We didn’t add any styles to the column except CSS reset. Now to make it look nice, add margin, border and boder-radius.
We’ll also add some padding to our task list. I’ll add it directly to the title and task list, not the container, so they’ll have some distance from the edge of the box.
The reason why I’m doing this is because I’m going to highlight them later when I drag, and I want the color to fill up to the edges. You can also use your style methods or spacing to create your list.
We want our task list to return a list of tasks, so we want to render a list of task components, but we haven’t created one yet. Import task, because it hasn’t been created yet, so create it first.
Now create our task component and return the task content for the moment to let us know we passed in the correct data. Ok, we can see the task content of the incoming column rendered.
Let’s improve the style. Again, we create the container and use it to wrap the task content. The task list is rendered.
Make the list look better. We give it a border, some inner padding, and have each item push the item after it down a bit. Add a border-radius because it looks like a column.
We rendered our to-do list.
withReact-beautiful-dnd
To render the list
In class, we usestyled-components
theinnerRef callbackCome for usstyled components
To obtainDOM ref
.
If you weren’t therereact
usedref
Before doing so, I suggest you take a look at:
React ref documentation
Manipulate the DOM with React Refs
Tips for REF
In the React element, the callback to ref
If it is
A common approach is to create your own innerRef callback that allows your component to return the specified Dom node
Code: codesandbox. IO/embed/githu…
To add reorder to your task list, install a dependency called react-beautiful-dnd. Ok, good.
npm install react-beautiful-dnd
Copy the code
Before exploring further, take a look at the components that make up the React-beautiful-DND. It is made up of three different components. The first one is DragDropContext, which is a component that wraps around the part of the application that we need to drag.
The Droppable creation area can be put in, which contains the Draggable component, which is a component that can be dragged and dropped on the Droppable. To make the contents of the column dragable, we wrap it with DragDropContext.
First, we import the DragDropContext from react-beautiful-dnd. The DragDropContext component has three callbacks. OnDragStart is called when the drag occurs. OnDragUpdate is called when the drag changes, such as an item moving to a new location. OnDragEnd is called at the end of the drag.
DragDropContext only onDragEnd has to be passed in. It is the responsibility of your onDragEnd function to update your state synchronously, reflecting the result of the drag. Let’s leave the function blank and implement it later.
We’re going to enhance the column component. Import the Droppable component from react-beautiful-dnd and put our task list into the Droppable. Droppable requires only a prop: droppableId.
This id needs to be unique in DragDropContext. We’re going to use the ID of column. You can see the app error: “Children are not a function.” Droppable uses the render props design pattern, which expects wrapped child components to be functions that return components.
One reason for using render props is that the React-beautiful-DND doesn’t want to create any DOM nodes. You create the components you want. React-beautiful-dnd incorporates your existing structure.
The first argument to the function is provided, which is an object that serves several important purposes. It has a property for droppableProps. These props need to be applied to the component that you want to use as a drag area.
In the documentation, we explicitly list all of these props. You can use them individually, or even patch them to improve them. However, we are not going to go there.
In general, you can expand provided. DroppableProps directly on your component. The Provided object has a property called innerRef, which is a function that gives the DOM node in your component to react-beautiful-dnd.
Styled – Component has a callback prop called innerRef, which returns the DOM node of the component. We can pass the provided. InnerRef to it. The last thing to do is insert placeholder in droppable, provided. Placeholder.
The React placeholder is a React element that is used as a sub-component of the Droppable to increase the size of the droppable drop area during drags. Our Droppable is ready.
Let’s go to the task component and make it draggable. Import the Draggable component from react-beautiful-dnd. Now I wrap the container component with the Draggable component.
The Draggable component has two necessary props. The first is draggable-ID, which is assigned with the id of the task. The second is index. We do not currently pass indexes to the task component. Let’s go back to the column component.
Column components map the tasks in PROP into task components. The second argument to the map function is the index of the array. We pass the index to the task component. If we go back to the mission component, we still have a problem.
Just like Droppable, Draggable expects its child components to be functions. The first function argument is a Provided object, just like the Provided object in droppable.
The Provided object has a property called draggableProps, which are used on components that need to be dragged so that they can respond to user input. The Provided has another property called dragHandleProps. These props are used to control the drag part, thus allowing that part to control the entire component.
You can take advantage of this by dragging large components with only a small part of them. In our application, we want the entire task to be able to drag, so apply props to the same element. Just like droppable, we’re going to supply refs to draggable.
Now let’s look at our application. We can drag items without using a mouse or keyboard. That’s nice. When we drag the item, we can see the contents on the back of it. That doesn’t look good.
Back to our task component. Add background color. White is fine. Now when we move a project, we don’t see what’s behind it. Well, we have a reordering experience that looks good.
You might notice that when I drag, the sort doesn’t stay. To implement persistence, we implement our sorting logic in the onDragEnd callback.
usingonDragEnd
Callback persistence list sorting
This video shows you how to persist the results of drag and drop interactions, okay
To achieve the effect, you will achieveonDragEnd
Callback function, which is called at the end of each drag. The function receives aresult
Object. We will usesource
anddestination
Property to retrieve the order of the task list
Code: codesandbox. IO/embed/githu…
Now we can drag and drop the contents of the task list, but the result of the interaction is not persisted, so after the drag and drop is complete, the task list returns to its original state. We have to persist it in onDragEnd.
First, what is a Result object? What information are we given? So here’s an example, the Result object. Result has draggableId, which is the id of the element that the user dragged. It has a type property, which we’ll talk about later, and a drag and drop reason, which will be drop or cancel.
In general, it’s not very important to know if the user is dragging and dropping or using the cancel key, but you can get the information if you need it. We now use two really important objects, source and Destination objects.
These objects contain location information, where the drag starts and ends. In this project, the Draggable component starts at column-1 with index 0 and ends at column-1 with index 1. Destination may be null, for example when a user drags out a list.
You can get the information we’re interested in from the Result object. If there is no destination and nothing to do, we can just quit.
I would like to add some small checks to check for changes in drag positions. You can do this by checking the draggableids of source and destination, and whether their indexes are consistent. If both checks are true, it means the user has put the drag item back where it was, and nothing needs to be done.
We need to reorder the taskIds array. We get the columns in the state first. I’ve got the DROppable ID from source to query the columns in the state.
I could have just used column-1 to get the column, because I knew there was only one column, but using source.droppableId would have made the program more robust. If I use column-1, I’m going to change the initial data, and I’m going to change the idcolumn-1.
When I update, I generally avoid changing the old state. Instead, I copy a new object and change it.
We need to move the old index in the taskIds array to the new index. What can Splice do? It removes the element of the specified index.
We have to use splice one more time. This time we use the index of destination, but instead of deleting anything, we insert the draggableId, which is the ID of the task. There are different ways to sort an array, and this is just one of them.
I’m going to create a new column. It has the same properties as the old column, just a new array. We’re going to put it in the state.
I use object expansion to maintain the original state on the one hand and merge the properties that need to be changed on the other.
I’m going to insert a new column, and it’s going to overwrite the old column. Technically, we don’t have to expand it, because we only have one column, but I think it’s a good idea to do that. Call this.setState, which updates the React component. Going back to the task list, we can say sort persistence is done.
We have optimistically updated the UI without waiting for several confirmations. How you save changes depends on your state solution and server architecture.
A simple strategy to change persistence would be to optimistically update the call terminal to let your server know about reordering.
(Optimistic update is to change the view first and then send the change request to the back end.)
Drag onreact-beautiful-dnd
thesnapshot Values
Customize the appearance of an application
<Draggable />
and<Droppable />
Components lift snapshot objects of their child functions. Snapshot objects can be used to create beautiful visual queues as the drag occurs
Code: codesandbox. IO/embed/githu…
The task list reordering looks great. What if we want to add styles when we drag? React-beautiful-dnd lift loads of information about the state of drag interactions, and it can help you add visual effects.
You can update anything, and as you drag, it doesn’t change the dimension of your draggable and Droppable components. Changing the background color of a component is a good way to indicate what is moving and what has been dragged recently.
How do we do that? Back to the task component, the second parameter to the component function is snapshot, which contains a set of properties that allow you to add styles as you drag.
We have the Draggable snapshot object. There are two properties in snapshot. The first is Boolean flagisDragging, which has a value true when draggable is dragged. The other one is draggingOver, which is the ID of a Droppable when a draggable is dragged into the Droppable area. If draggable is dragging and does not enter the Droppable region, draggingOver is null.
When the task is dragged, we will use snapshot to change the background color of the task. What I now do is pass isDragging as a prop to my style component, which has the value of the snapshot.isdragging attribute.
Using the style component API, I can set the component’s background color according to prop. If isDragging is true, I want to set the background color to bright green, otherwise white.
Now as we drag the task, the background color of the drag object changes to light green. The same can be done in Droppable, where the second parameter to the droppable function is also snapshot.
The Snapshot of droppable has two properties. First, it is a Boolean flag called isDraggingOver, which is true when draggable drags into the Droppable region. The other property is draggingOverWith, which is the ID of the draggable that enters the Droppable. If there are no draggable in the Droppable region, its value is null.
When dragging, we need to change the background color of the task list. I’m going to give isDraggingOver as a prop to the task style component. I want it to go with the Boolean value of snapshot.isDraggingOver.
If isDraggingOver for the task list is true, I change the background color of the task list to sky blue. Otherwise, it is white. When I lift a task, the background color of the task list is naive, and when I move off the list, the background color changes back to white.
I like to add a transition effect to my Droppables, which makes the color shift look more appealing when you drag it between droppables.
withdragHandleProps
To design drag control
inreact-beautiful-dnd
The draggable element is separate from the drag handle element. This lecture will explain the difference and show you how to deal with itdraggable
The control of
<Draggable/>
The provided object, which has a property calleddragHandleProps
. This property allows us to specify<Draagable/>
Which part can control the drag. You will see how to pass properties to components to design controls.
Code: codesandbox. IO/embed/githu…
The drag handling is part of the draggable and can be used to control the drag of the entire draggable. For our task component, the draggable and drag handling are the same component. This means that we can drag components from any part of the task component.
However, this is not necessarily the case. Now create a new component that controls the task component. Now we have an error because we haven’t created the component yet.
I used div elements to create drag handling, but you can use any element. I gave it 20 pixels wide, 20 pixels high, the background color was orange, and a 4 pixel border RADIUS. We want the drag processing element to be on the left side of the task component.
I’m going to make our container a Flex layout. Even though we’ve created the drag handler element, we can still drag on any part because we’re still passing the dragHandleProps to the container.
To make the drag-handling component work, what we need to do is expand the dragHandleProps inside the component. Now we can no longer drag draggable from content. We can only use the Handle to drag, and the same is true for keyboard control.
Custom drag controls are very useful. However, in this case, I don’t think it’s necessary. I think the experience of being able to drag around in task components is nice. In the next video, I’m not going to keep this change.
usingonDragEnd
Move items between columns
In this lesson, we place a multi-column task list that can be moved between different columns.
Now our application has multiple columns and needs to be refactoredonDragEnd
Handle multiple column cases. We will add new logic to move tasks to other columns in the state.
Code: codesandbox. IO/embed/githu…
In this lesson, we will add multiple columns so that tasks can be moved between columns. First, go back to the original data.
Now there’s only one column. I added two more columns, one in progress column and the other done column. I also need to increment the ids of these columns to sort the array of columns.
Our application now renders three columns. We need to update the style so that the columns are side by side. Go back to index.js and add a component called Container that will wrap our column.
[00:58] This container will be a flex parent that will align the items next to each other. I have an important style components here. I’ll just do that. Our columns are being printed next to each other. However, that to do column which has tasks in it is much wider than the other ones.
It is a Flex parent that keeps the children side by side. However, the to do column is wider than the others.
Back to the column component. There are no container components. I added width to these columns. Now, all columns have the same width. Zoom in a little bit, and we can see what happens.
When we hover over other columns with the mouse, they are not highlighted. This is because the progress column and the complete column have no tasks and now have no height. To solve this problem, we make the container the flex parent, with Flex-direction column.
The child elements are now arranged vertically. For our task list, I want the Flex element to be larger. Now the Flex box fills up the available space. If I wander around these columns, I get the right color.
It is worth mentioning that I want to add a minimum height to the Droppable component so that tasks can still be placed in the column if all columns are empty, otherwise it would not be easy to place tasks in the column.
So if we go back to the app, if we put the task in the progress column, the task goes back to where it was. We need to update the reordering logic of the onDragEnd function to handle inter-column movement.
In index.js, we used the source.droppableId attribute to query columns. In the case of a single column, drag is fine. However, this is not enough to handle multi-column cases.
We use two variable names to store the start and end columns: start and end. If they point to the same column, the previous logic is executed.
If I reorder the same column, the result will still be saved. Now to deal with the different columns, we’re going to do the same thing we did before.
I’ve created a new starting task-ID array that matches the old one, and I’m going to remove the drag-and-drop task ids from the array. On the other hand, I also create a new start column, which is the same as the old one, but without the new start task-ID array.
I will also copy a new array for the terminated task-ID array, which is the same as the old one. I’m going to use splice to insert the draggableId at the specified index. I create a new column that holds the new terminal column with the new task-ID array.
Finally, we create a new state object that has the same properties as the old one, but the columns and task data have been updated.
The process is similar to rendering a single column sort before. The difference is that we are dealing with different columns with the behavior of different components, not the same column.
Now our application can move tasks to any column, which can also be done with the keyboard.
Movement condition constraint
Now that we can move tasks between task lists, we probably don’t want the user to be able to move to an arbitrary location. This lesson will explore dragging and dropping if conditions are limited.
React-beautiful-dnd provides robust apis to configure what can be dragged and where.isDragDisabled
Can be set in the<Draggable />
and<Droppable />
And the<Droppable />
The type prop (Type) gives you fine-grained control, allowing you to implement any business logic and control what can be dragged or dropped.
(Translator’s note: The examples in this section are buggy. If you move tasks randomly between different columns, it will give you an error, and I don’t understand why. But if you don’t allow a component to move in the first place, that’s fine.)
Code: codesandbox. IO/embed/githu…
With react-beautiful-DND, just with prop isDragDisabled, you can control what you can drag and where you can drop it
When isDragDisabled is true, it prevents the Draggable from being dragged. What I want to do is make the component with ID task-1 immovable. We can see that the first task component is not removable, but the rest is fine.
I’m going to pull it out and put variables in so that it can be applied to the style component. I’m going to use a ternary expression to set the background color. If the Draggable component is immovable, give it a light gray color.
We can now see more easily what is immovable. IsDragDisabled prevents Draggable from dragging, but it can still be reordered.
You can do whatever you want with isDragDisabled. It can be based on some complex business logic. As we go to the column component, there are two available mechanisms to control where the hand midmoon bow Draggable can be placed.
The simplest mechanism is to use Droppable type Prop, where you can provide optional types to Droppable. A Draggable can only be dragged into Droppable of the same type.
I select the Droppable type based on the id of the column. The third column has the Done type, but the first two columns have the Active type.
This setting allows me To move between the to-do and in-progress columns, but not To the Done column. The second mechanism that controls where you can drag and drop is isDropDisabled for Droppable.
If isDropDisabled is set to true, no Draggable can be dragged in, even if it is of the same type. You can change isDropDisabled dynamically, even during dragging.
I set isDropDisabled in Droppable. With this prop, we can make the task move only to the right.
I created an onDragStart function to capture the index of the column at the start of the drag. When the drag is done, I want to make sure I clear the index.
I’m going to bind the onDragStart function to the DragDropContext. I get the index of the column from the array’s map function. I’m going to create a variable called isDropDisabled.
IsDropDisabled is set to true when the number of indexes retrieved from the map is less than the index of the starting column. This prevents dragging backwards.
I’m going to pass it to column. I can move a task from the To-do column To the In-progress column, but NOT back To the to-do column, only To the Done column.
Using the propdirection
Sort horizontally
In this video, we’re going to show you how to create a horizontal sort, okayDroppable
.
The component provides us with a direction prop that we can use to set a list of data to be sortable in the vertical or horizontal plane.
Code: codesandbox. IO/embed/githu…
Instructor: [00:00] Up to now, we’ve only looked up vertical reordering in our application. React-beautiful-dnd also supports reordering draggables on the horizontal plane.
Right now, we just see vertical sort. React-beautiful-dnd also supports horizontal sorting.
Let’s go back to the original data. I’m only going to do one column in this video. I made the task list the Flex parent.
We can see items from left to right. We removed the width of the container because we no longer needed it, and flex-growing, I mean the height property.
In the task component, I no longer render everything, just the first character. I gave our container a width of 40 pixels, a height of 40 pixels, and changed the border-radius to 50% to make it round.
I don’t want to leave space at the bottom of the task list, but put it on the right. I used flex boxes to center the content horizontally and vertically. Our list of tasks is ready, now arranged horizontally.
As I began to drag, I felt something strange, not what we were expecting. We need to go back to the column component and change the Droppable prop, which has an optional prop called Direction.
By default, Droppable is sorted vertically. You can have a horizontally sorted list by changing the direction of prop to horizontal. If our example, we can say that we can reorder horizontally.
Keyboard manipulation is also effective. When we focus on a draggable, we get the default focus profile. This is kind of interesting, because our task ordering becomes universal.
Add a style to the focus state, cancel the default outline, change the color of the border to red, and make the border wider.
reorder
In this lesson, we apply the techniques we learned earlier to reordering columns.
And to do that, you need to use<Droppable/>
To wrap the columns, sort them horizontally to make the columns draggable. And you can see that this is similar to the task sequencing. We’re going to use nesting<Draggable />
和 <Droppable />
Components, andDroppable
Type prop to implement column sorting.
Code: codesandbox. IO/embed/githu…
In this lesson, we’ll add column sorting. I’ve shown you how to do it. Now we have several Droppable components sorted vertically.
These are our task lists, highlighted here in yellow. They have tasks, draggable components. We add a Droppable parent element, which sorts the children horizontally, and then turns the column component into a draggable component.
This method contains nested use of draggable and Droppable. We sort the columns horizontally and the tasks vertically.
Change the initial data slightly to remove the third column, so it’s easier to see the effect. Import droppable from react-beautiful-dnd to create droppable sorted horizontally.
I wrapped our container component with a Droppable. It doesn’t matter what its ID is, because it doesn’t interact with other Droppables. Call it all-columns.
We need to set the droppable orientation to horizontal so that our columns are sorted horizontally. Also, we will add type prop with the column value. Give the droppable of all-columns a different type so that it does not conflict with the droppable of the task list.
Set the rest of the droppable. I gave this component props for droppable, and a DOM reference. I also added placeholders for Droppable. Now process the column component to make it draggable. First import draggable from react-beautiful-dnd.
Wrap the entire column in the DragGable, using the column ID as the DRAGgable ID. Draggable also needs an index, which indicates the location of the droppable. We don’t have the index now, so we need to provide it.
The second argument to the map function is the index of the array. We can pass it directly to the column component.
I applied the Draggable props to our container, and I also applied the innerRef function, but I didn’t apply the dragHandleProps yet, which caused an error.
We use column headers as drag controls to add types to the container that wraps the task.
Let’s take a look at our application. We can still reorder tasks. When the columns are sorted, the style looks interesting, but when the following is placed, the error is reported. There’s something we need to do.
We encountered an error because we were also updating the sorting logic of the onDragEnd function. We pull the Type attribute from the Result object to know whether we are dragging a column or a task.
We need to add some logic to the column to handle its sorting. I create a new column sort array that has the same value as the old one. I want to remove the old column ID from the original index and insert it in the new location.
I’m going to create a new state object that is the same as the old one, but with a new column sort array. Let’s go back to our application. The reordering result of the column is saved. However, when I drag, I can still see what’s behind the column header.
Instead of just adding a background color for the title, I add a background color for the entire column. I’m going to change the task list, add a conditional judgment, and set the background color, and instead of setting it to white, I’m going to inherit the white of the container.
Now I drag the column and you don’t see what’s behind it. We can now reorder tasks, move tasks to other columns, sort them. We can also use the keyboard to operate.
usingshouldComponentUpdate
和 PureComponent
To optimize performance
We don’t have to re-renderDraggable
和 Droppable
Components update styles by building<InnerList/>
Component, which will take advantage of ReactshouldComponentUpdate
Lifecycle hook function to prevent rendering.
Then you’ll know how to use ReactPureComponent
To achieve the same optimization.
Code: codesandbox. IO/embed/githu…
In this lesson, I’m going to talk about some important performance optimizations that you can use to make your application run faster.
One performance bottleneck for React is the reconciliation process. Simply put, some components don’t change and you don’t want to re-render them. I’m going to use React in Chrome’s Developer tools plugin, which can be downloaded from Chrome’s web store.
This plugin has a super useful feature called Highlight Updates. With this feature, the developer tools highlight the rendered components.
As the column drags, I want to change the background color from sky blue to light gray so we can see what’s going on.
When I pick up the task, you can see all the tasks highlighted in blue. This shows the component’s render function being called. When the droppable column calls its subfunctions, it renders all of its tasks.
The droppable function is called when the value of the snapshot function changes. This happens whether you enter or leave. As you can see, when I enter or leave, all tasks turn blue, which means the render method is called.
We want our task list to respond when the snapshot value changes, just as we want to drag when the background color changes. However, we don’t want to render all tasks just to make the style change. I’m going to replace it with a new component.
We travel the mapping back to the task component’s logic into the InnerList component. I’m going to add the shouldComponentUpdate lifecycle method.
If the new task array is equal to the original array reference, we skip rendering. If the reference changes, we allow rendering. Now as we drag the task, we can update the background color without rendering unnecessarily.
When I drag a column, all tasks in the column are rendered. You can see that all tasks turn blue, which means rendering has taken place.
Here is the droppable of the column, when I drag the column, all tasks render, because the snapshot value changes, even if the droppable function is not called.
When the Droppable function is called, it returns the new list component. As with the column component, we want to avoid rendering the droppable child component, in this case, the container component when dragging.
Instead of returning a column component, we return a new InnerList component that renders the column component. The key difference is that instead of creating a new array of tasks on the fly, it is the mapping of task objects.
The InnerList component does exactly what we did in the Droppable function before; if left intact, there is no performance optimization.
If no prop changes, we can make a conditional judgment to prevent rendering. The key to optimization is that instead of dynamically generating an array of tasks, you pass in a map of the entire task. These three properties therefore do not change as you drag.
Add styles to columns while dragging, no rendering takes place. We can make the component inherit PureComponent, which is the same validation as shouldComponentUpdate.
Now when we drag the list, we see that the task is no longer highlighted blue, meaning it is no longer re-rendered.
(Translator’s note: There is still a section on interaction with Screen Reader, but I think the content is not important, so I will not translate it. If you are interested, you can check it out for yourself.)