Skip to content

Commit de148ed

Browse files
authored
Optimize the plots sections to reduce the number of useless re-renderings (#3341)
* Optimize the plots sections to reduce the number of useless re-renderings * Revert to section variable name to reduce number of changes
1 parent 1651088 commit de148ed

File tree

3 files changed

+58
-60
lines changed

3 files changed

+58
-60
lines changed

webview/src/plots/components/templatePlots/TemplatePlots.tsx

Lines changed: 30 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,11 @@
11
import { TemplatePlotGroup } from 'dvc/src/plots/webview/contract'
2-
import React, {
3-
DragEvent,
4-
useState,
5-
useEffect,
6-
useRef,
7-
useCallback
8-
} from 'react'
2+
import React, { DragEvent, useState, useCallback } from 'react'
93
import cx from 'classnames'
104
import { useDispatch, useSelector } from 'react-redux'
115
import { MessageFromWebviewType } from 'dvc/src/webview/contract'
126
import { AddedSection } from './AddedSection'
137
import { TemplatePlotsGrid } from './TemplatePlotsGrid'
14-
import { PlotGroup } from './templatePlotsSlice'
8+
import { PlotGroup, updateSections } from './templatePlotsSlice'
159
import { removeFromPreviousAndAddToNewSection } from './util'
1610
import { sendMessage } from '../../../shared/vscode'
1711
import { createIDWithIndex, getIDIndex } from '../../../util/ids'
@@ -30,9 +24,7 @@ export enum NewSectionBlock {
3024
}
3125

3226
export const TemplatePlots: React.FC = () => {
33-
const { plotSections, size } = useSelector(
34-
(state: PlotsState) => state.template
35-
)
27+
const { size, sections } = useSelector((state: PlotsState) => state.template)
3628
const draggedOverGroup = useSelector(
3729
(state: PlotsState) => state.dragAndDrop.draggedOverGroup
3830
)
@@ -43,29 +35,30 @@ export const TemplatePlots: React.FC = () => {
4335
(state: PlotsState) => state.webview.selectedRevisions
4436
)
4537

46-
const [sections, setSections] = useState<PlotGroup[]>(plotSections)
4738
const [hoveredSection, setHoveredSection] = useState('')
4839
const nbItemsPerRow = size
49-
const shouldSendMessage = useRef(true)
5040
const dispatch = useDispatch()
5141

52-
useEffect(() => {
53-
shouldSendMessage.current = false
54-
setSections(plotSections)
55-
}, [plotSections, setSections])
56-
57-
useEffect(() => {
58-
if (sections && shouldSendMessage.current) {
59-
sendMessage({
60-
payload: sections.map(section => ({
61-
group: section.group,
62-
paths: section.entries
63-
})),
64-
type: MessageFromWebviewType.REORDER_PLOTS_TEMPLATES
65-
})
66-
}
67-
shouldSendMessage.current = true
68-
}, [sections])
42+
const sendReorderMessage = useCallback((sections: PlotGroup[]) => {
43+
sendMessage({
44+
payload: sections.map(section => ({
45+
group: section.group,
46+
paths: section.entries
47+
})),
48+
type: MessageFromWebviewType.REORDER_PLOTS_TEMPLATES
49+
})
50+
}, [])
51+
52+
const setSections = useCallback(
53+
(sections: PlotGroup[]) => {
54+
/* Although the following dispatch duplicates the work the reducer will do when the state returns
55+
from the extension, this is necessary to not see any flickering in the order as the returned state
56+
sometimes takes a while to come back */
57+
dispatch(updateSections(sections))
58+
sendReorderMessage(sections)
59+
},
60+
[dispatch, sendReorderMessage]
61+
)
6962

7063
const handleDropInSection = useCallback(
7164
(
@@ -94,16 +87,14 @@ export const TemplatePlots: React.FC = () => {
9487

9588
const setSectionEntries = useCallback(
9689
(index: number, entries: string[]) => {
97-
setSections(sections => {
98-
const updatedSections = [...sections]
99-
updatedSections[index] = {
100-
...sections[index],
101-
entries
102-
}
103-
return updatedSections
104-
})
90+
const updatedSections = [...sections]
91+
updatedSections[index] = {
92+
...updatedSections[index],
93+
entries
94+
}
95+
setSections(updatedSections)
10596
},
106-
[setSections]
97+
[setSections, sections]
10798
)
10899

109100
if (sectionIsLoading(selectedRevisions)) {
@@ -235,7 +226,6 @@ export const TemplatePlots: React.FC = () => {
235226
useVirtualizedGrid={useVirtualizedGrid}
236227
nbItemsPerRow={nbItemsPerRow}
237228
parentDraggedOver={draggedOverGroup === groupId}
238-
entries={section.entries}
239229
/>
240230
</div>
241231
)

webview/src/plots/components/templatePlots/TemplatePlotsGrid.tsx

Lines changed: 8 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import cx from 'classnames'
22
import { Section } from 'dvc/src/plots/webview/contract'
3-
import React, { useEffect, useState, useCallback, useMemo } from 'react'
3+
import React, { useEffect, useCallback, useMemo } from 'react'
44
import { useDispatch, useSelector } from 'react-redux'
55
import { changeDisabledDragIds, changeSize } from './templatePlotsSlice'
66
import { VirtualizedGrid } from '../../../shared/components/virtualizedGrid/VirtualizedGrid'
@@ -24,7 +24,6 @@ interface TemplatePlotsGridProps {
2424
setSectionEntries: (groupIndex: number, entries: string[]) => void
2525
useVirtualizedGrid?: boolean
2626
nbItemsPerRow: number
27-
entries: string[]
2827
parentDraggedOver?: boolean
2928
}
3029

@@ -36,12 +35,13 @@ export const TemplatePlotsGrid: React.FC<TemplatePlotsGridProps> = ({
3635
setSectionEntries,
3736
useVirtualizedGrid,
3837
nbItemsPerRow,
39-
entries,
4038
parentDraggedOver
4139
}) => {
4240
const dispatch = useDispatch()
43-
const [order, setOrder] = useState<string[]>([])
4441
const currentSize = useSelector((state: PlotsState) => state.template.size)
42+
const entries = useSelector(
43+
(state: PlotsState) => state.template.sections[groupIndex].entries
44+
)
4545

4646
const disabledDragPlotIds = useSelector(
4747
(state: PlotsState) => state.template.disabledDragPlotIds
@@ -64,10 +64,6 @@ export const TemplatePlotsGrid: React.FC<TemplatePlotsGridProps> = ({
6464
e.stopPropagation()
6565
}, [])
6666

67-
useEffect(() => {
68-
setOrder(entries)
69-
}, [entries])
70-
7167
useEffect(() => {
7268
const panels = document.querySelectorAll('.vega-bindings')
7369
return () => {
@@ -88,11 +84,8 @@ export const TemplatePlotsGrid: React.FC<TemplatePlotsGridProps> = ({
8884
}
8985
}, [addDisabled, removeDisabled, disableClick])
9086

91-
const setEntriesOrder = (order: string[]) => {
92-
setOrder(order)
93-
87+
const setEntriesOrder = (order: string[]) =>
9488
setSectionEntries(groupIndex, order)
95-
}
9689

9790
const plotClassName = cx(styles.plot, {
9891
[styles.multiViewPlot]: multiView
@@ -107,7 +100,7 @@ export const TemplatePlotsGrid: React.FC<TemplatePlotsGridProps> = ({
107100

108101
const items = useMemo(
109102
() =>
110-
order.map((plot: string) => {
103+
entries.map((plot: string) => {
111104
const colSpan =
112105
(multiView &&
113106
plotDataStore[Section.TEMPLATE_PLOTS][plot].revisions?.length) ||
@@ -134,7 +127,7 @@ export const TemplatePlotsGrid: React.FC<TemplatePlotsGridProps> = ({
134127
)
135128
}),
136129
[
137-
order,
130+
entries,
138131
plotClassName,
139132
addEventsOnViewReady,
140133
currentSize,
@@ -145,7 +138,7 @@ export const TemplatePlotsGrid: React.FC<TemplatePlotsGridProps> = ({
145138

146139
return (
147140
<DragDropContainer
148-
order={order}
141+
order={entries}
149142
setOrder={setEntriesOrder}
150143
items={items}
151144
group={groupId}

webview/src/plots/components/templatePlots/templatePlotsSlice.ts

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,17 +12,17 @@ export type PlotGroup = { group: TemplatePlotGroup; entries: string[] }
1212
export interface TemplatePlotsState extends Omit<TemplatePlotsData, 'plots'> {
1313
isCollapsed: boolean
1414
hasData: boolean
15-
plotSections: PlotGroup[]
1615
plotsSnapshots: { [key: string]: string }
16+
sections: PlotGroup[]
1717
disabledDragPlotIds: string[]
1818
}
1919

2020
export const templatePlotsInitialState: TemplatePlotsState = {
2121
disabledDragPlotIds: [],
2222
hasData: false,
2323
isCollapsed: DEFAULT_SECTION_COLLAPSED[Section.TEMPLATE_PLOTS],
24-
plotSections: [],
2524
plotsSnapshots: {},
25+
sections: [],
2626
size: DEFAULT_SECTION_SIZES[Section.TEMPLATE_PLOTS]
2727
}
2828

@@ -48,6 +48,7 @@ export const templatePlotsSlice = createSlice({
4848
entries: section.entries.map(entry => entry.id),
4949
group: section.group
5050
}))
51+
5152
const plots = action.payload.plots?.flatMap(section => section.entries)
5253
const plotsIds = plots?.map(plot => plot.id) || []
5354
const snapShots = addPlotsWithSnapshots(plots, Section.TEMPLATE_PLOTS)
@@ -56,15 +57,29 @@ export const templatePlotsSlice = createSlice({
5657
return {
5758
...state,
5859
hasData: !!action.payload,
59-
plotSections,
6060
plotsSnapshots: snapShots,
61+
sections:
62+
JSON.stringify(plotSections) === JSON.stringify(state.sections)
63+
? state.sections
64+
: plotSections,
6165
size: Math.abs(action.payload.size)
6266
}
67+
},
68+
updateSections: (state, action: PayloadAction<PlotGroup[]>) => {
69+
return {
70+
...state,
71+
sections: action.payload
72+
}
6373
}
6474
}
6575
})
6676

67-
export const { update, setCollapsed, changeSize, changeDisabledDragIds } =
68-
templatePlotsSlice.actions
77+
export const {
78+
update,
79+
setCollapsed,
80+
changeSize,
81+
changeDisabledDragIds,
82+
updateSections
83+
} = templatePlotsSlice.actions
6984

7085
export default templatePlotsSlice.reducer

0 commit comments

Comments
 (0)