Skip to content

Commit 58577fe

Browse files
reduce re-rendering by adding memoziation
1 parent 02b6166 commit 58577fe

File tree

9 files changed

+116
-59
lines changed

9 files changed

+116
-59
lines changed

client/packages/lowcoder/src/comps/comps/containerComp/containerView.tsx

+4-2
Original file line numberDiff line numberDiff line change
@@ -439,9 +439,9 @@ export const InnerGrid = React.memo((props: ViewPropsWithSelect) => {
439439
isRowCountLocked,
440440
onPositionParamsChange,
441441
onRowCountChange,
442-
positionParams,
442+
JSON.stringify(positionParams),
443+
JSON.stringify(props.containerPadding),
443444
props.dispatch,
444-
props.containerPadding,
445445
]
446446
);
447447
const setSelectedNames = useCallback(
@@ -454,6 +454,8 @@ export const InnerGrid = React.memo((props: ViewPropsWithSelect) => {
454454
const { width, ref } = useResizeDetector({
455455
onResize,
456456
handleHeight: isRowCountLocked,
457+
refreshMode: 'debounce',
458+
refreshRate: 100,
457459
});
458460

459461
const itemViewRef = useRef<GirdItemViewRecord>({});

client/packages/lowcoder/src/comps/comps/responsiveLayout/responsiveLayout.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ type ColumnContainerProps = Omit<ContainerBaseProps, 'style'> & {
136136
style: ResponsiveLayoutColStyleType,
137137
}
138138

139-
const ColumnContainer = (props: ColumnContainerProps) => {
139+
const ColumnContainer = React.memo((props: ColumnContainerProps) => {
140140
return (
141141
<InnerGrid
142142
{...props}
@@ -145,7 +145,7 @@ const ColumnContainer = (props: ColumnContainerProps) => {
145145
style={props.style}
146146
/>
147147
);
148-
};
148+
});
149149

150150
const ResponsiveLayout = (props: ResponsiveLayoutProps) => {
151151
const screenInfo = useScreenInfo();

client/packages/lowcoder/src/layout/calculateUtils.tsx

-1
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,6 @@ export function calcGridItemSizePx(
9393
const width = calcGridItemWHPx(w, colWidth, margin[0], false);
9494

9595
const isTouchSBound = top ? isTouchBound(maxRows, rowHeight, h, top) : false;
96-
// console.log('positionParams',positionParams);
9796
const height = calcGridItemWHPx(h, rowHeight, margin[1], isTouchSBound);
9897
return { width, height };
9998
}

client/packages/lowcoder/src/layout/compSelectionWrapper.tsx

+59-29
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,16 @@ import React, {
1111
MouseEventHandler,
1212
useCallback,
1313
useContext,
14+
useMemo,
1415
useRef,
1516
useState,
1617
} from "react";
1718
import ReactResizeDetector, { useResizeDetector } from "react-resize-detector";
1819
import styled, { css } from "styled-components";
1920
import { EllipsisTextCss } from "lowcoder-design";
2021
import { draggingUtils } from "./draggingUtils";
21-
import { ResizeHandleAxis } from "./gridLayoutPropTypes";
22+
import type { ResizeHandleAxis } from "./gridLayoutPropTypes";
23+
import { isEqual } from "lodash";
2224

2325
export type DragHandleName = "w" | "e" | "nw" | "ne" | "sw" | "se";
2426
type NamePos = "top" | "bottom" | "bottomInside";
@@ -273,7 +275,7 @@ export const CompSelectionWrapper = React.memo((props: {
273275
}
274276
setHover(true);
275277
},
276-
[setHover]
278+
[nameDivRef.current, setHover]
277279
);
278280
const onMouseOut = useCallback(
279281
(e: MouseEvent<HTMLDivElement>) => {
@@ -287,39 +289,57 @@ export const CompSelectionWrapper = React.memo((props: {
287289
}
288290
setHover(false);
289291
},
290-
[setHover]
292+
[nameDivRef.current, setHover]
291293
);
292294

293-
const selectableDivProps = props.isSelectable
294-
? {
295-
onMouseOver,
296-
onMouseOut,
297-
onClick: props.onClick,
298-
$hover: hover || undefined,
299-
$showDashLine: editorState.showGridLines() || props.hidden,
300-
$isSelected: props.isSelected,
301-
$isHidden: props.hidden,
302-
}
303-
: {
304-
$hover: undefined,
305-
$showDashLine: false,
306-
$isSelected: false,
307-
$isHidden: false,
308-
};
295+
const selectableDivProps = useMemo(() => {
296+
return props.isSelectable
297+
? {
298+
onMouseOver,
299+
onMouseOut,
300+
onClick: props.onClick,
301+
$hover: hover || undefined,
302+
$showDashLine: editorState.showGridLines() || props.hidden,
303+
$isSelected: props.isSelected,
304+
$isHidden: props.hidden,
305+
}
306+
: {
307+
$hover: undefined,
308+
$showDashLine: false,
309+
$isSelected: false,
310+
$isHidden: false,
311+
};
312+
}, [
313+
hover,
314+
props.hidden,
315+
props.isSelected,
316+
props.isSelectable,
317+
]);
318+
319+
const zIndex = useMemo(() => {
320+
return props.isSelected
321+
? Layers.compSelected
322+
: hover
323+
? Layers.compHover
324+
: props.hidden
325+
? Layers.compHidden
326+
: undefined;
327+
}, [
328+
hover,
329+
props.hidden,
330+
props.isSelected
331+
]);
309332

310-
const zIndex = props.isSelected
311-
? Layers.compSelected
312-
: hover
313-
? Layers.compHover
314-
: props.hidden
315-
? Layers.compHidden
316-
: undefined;
333+
const needResizeDetector = useMemo(() => {
334+
return props.autoHeight && !props.placeholder;
335+
}, [props.autoHeight, props.placeholder]);
317336

318-
const needResizeDetector = props.autoHeight && !props.placeholder;
319337
const { ref: wrapperRef } = useResizeDetector({
320338
onResize: props.onWrapperResize,
321339
handleHeight: needResizeDetector,
322340
handleWidth: false,
341+
refreshMode: 'debounce',
342+
refreshRate: 100,
323343
});
324344
// log.debug("CompSelectionWrapper. name: ", props.name, " zIndex: ", zIndex);
325345
const { nameConfig, resizeIconSize } = props;
@@ -369,8 +389,18 @@ export const CompSelectionWrapper = React.memo((props: {
369389
{!needResizeDetector && props.children}
370390
{needResizeDetector && (
371391
<ReactResizeDetector
392+
skipOnMount={
393+
props.compType === 'responsiveLayout'
394+
|| props.compType === 'columnLayout'
395+
|| props.compType === 'pageLayout'
396+
|| props.compType === 'splitLayout'
397+
|| props.compType === 'floatTextContainer'
398+
|| props.compType === 'tabbedContainer'
399+
|| props.compType === 'collapsibleContainer'
400+
|| props.compType === 'container'
401+
}
372402
refreshMode="debounce"
373-
refreshRate={250}
403+
refreshRate={100}
374404
onResize={props.onInnerResize}
375405
observerOptions={{ box: "border-box" }}
376406
>
@@ -380,4 +410,4 @@ export const CompSelectionWrapper = React.memo((props: {
380410
</SelectableDiv>
381411
</div>
382412
);
383-
});
413+
}, (prev, next) => isEqual(prev, next));

client/packages/lowcoder/src/layout/gridItem.tsx

+39-19
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,19 @@ const ResizableStyled = styled(Resizable)<{ $zIndex: number, isDroppable : boole
104104
*/
105105
export const GridItem = React.memo((props: GridItemProps) => {
106106
const position = useMemo(() =>{
107+
console.log('calculateGridItemPOistion', JSON.stringify({
108+
name: props.name,
109+
margin: props.margin,
110+
containerPadding: props.containerPadding,
111+
containerWidth: props.containerWidth,
112+
cols: props.cols,
113+
rowHeight: props.rowHeight,
114+
maxRows: props.maxRows,
115+
x: props.x,
116+
y: props.y,
117+
w: props.w,
118+
h: props.h,
119+
}));
107120
return calcGridItemPosition({
108121
margin: props.margin,
109122
containerPadding: props.containerPadding,
@@ -113,8 +126,8 @@ export const GridItem = React.memo((props: GridItemProps) => {
113126
maxRows: props.maxRows,
114127
}, props.x, props.y, props.w, props.h)},
115128
[
116-
props.margin,
117-
props.containerPadding,
129+
JSON.stringify(props.margin),
130+
JSON.stringify(props.containerPadding),
118131
props.containerWidth,
119132
props.cols,
120133
props.rowHeight,
@@ -123,7 +136,6 @@ export const GridItem = React.memo((props: GridItemProps) => {
123136
props.y,
124137
props.w,
125138
props.h,
126-
calcGridItemPosition,
127139
]
128140
);
129141

@@ -230,8 +242,8 @@ export const GridItem = React.memo((props: GridItemProps) => {
230242
y: yy,
231243
});
232244
}, [
233-
resizing,
234-
dragging,
245+
JSON.stringify(resizing),
246+
JSON.stringify(dragging),
235247
props.cols,
236248
props.maxRows,
237249
props.x,
@@ -417,7 +429,7 @@ export const GridItem = React.memo((props: GridItemProps) => {
417429
itemHeightRef.current = height;
418430
}
419431
adjustWrapperHeight(width, height);
420-
}, [itemHeightRef, adjustWrapperHeight]);
432+
}, [itemHeightRef.current, adjustWrapperHeight]);
421433

422434
/**
423435
* re-calculate the occupied gird-cells.
@@ -427,7 +439,7 @@ export const GridItem = React.memo((props: GridItemProps) => {
427439
*/
428440
const onWrapperSizeChange = useCallback(() => {
429441
adjustWrapperHeight(undefined, itemHeightRef.current);
430-
}, [itemHeightRef, adjustWrapperHeight]);
442+
}, [itemHeightRef.current, adjustWrapperHeight]);
431443

432444
const mixinChildWrapper = useCallback((child: React.ReactElement): React.ReactElement => {
433445
const {
@@ -535,6 +547,21 @@ export const GridItem = React.memo((props: GridItemProps) => {
535547

536548
const pos = useMemo(calcPosition, [calcPosition]);
537549

550+
const transform = useMemo(() => {
551+
return setTransform(
552+
pos,
553+
props.name,
554+
props.autoHeight,
555+
props.hidden,
556+
Boolean(draggingUtils.isDragging())
557+
)
558+
}, [
559+
JSON.stringify(pos),
560+
props.name,
561+
props.autoHeight,
562+
props.hidden
563+
]);
564+
538565
const render = useMemo(() => {
539566
let child = React.Children.only(children);
540567
// Create the child element. We clone the existing element but modify its className and style.
@@ -563,13 +590,7 @@ export const GridItem = React.memo((props: GridItemProps) => {
563590
cssTransforms: true,
564591
}),
565592
style: {
566-
...setTransform(
567-
pos,
568-
props.name,
569-
props.autoHeight,
570-
props.hidden,
571-
Boolean(draggingUtils.isDragging())
572-
),
593+
...transform,
573594
opacity: layoutHide ? 0 : undefined,
574595
pointerEvents: layoutHide ? "none" : "auto",
575596
},
@@ -580,11 +601,12 @@ export const GridItem = React.memo((props: GridItemProps) => {
580601
newChild = mixinDraggable(newChild, isDraggable);
581602
return newChild;
582603
}, [
583-
pos,
604+
JSON.stringify(transform),
605+
JSON.stringify(pos),
584606
children,
585607
elementRef,
586-
resizing,
587-
dragging,
608+
Boolean(resizing),
609+
Boolean(dragging),
588610
isDraggable,
589611
layoutHide,
590612
zIndex,
@@ -593,8 +615,6 @@ export const GridItem = React.memo((props: GridItemProps) => {
593615
props.className,
594616
props.style,
595617
props.static,
596-
props.autoHeight,
597-
props.hidden,
598618
setTransform,
599619
mixinChildWrapper,
600620
mixinResizable,

client/packages/lowcoder/src/layout/gridLayout.tsx

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import clsx from "clsx";
22
import { colord } from "colord";
3-
import { UICompType } from "comps/uiCompRegistry";
3+
import type { UICompType } from "comps/uiCompRegistry";
44
import { ModulePrimaryColor, PrimaryColor } from "constants/style";
5-
import _ from "lodash";
5+
import _, { isEqual } from "lodash";
66
import log from "loglevel";
77
import React, { DragEvent, DragEventHandler, MouseEventHandler, ReactElement } from "react";
88
import ReactResizeDetector from "react-resize-detector";
@@ -21,7 +21,7 @@ import {
2121
import { draggingUtils } from "./draggingUtils";
2222
import { FlyOverInfo, FlyStartInfo } from "./flyInfo";
2323
import { GridItem } from "./gridItem";
24-
import { GridLayoutProps } from "./gridLayoutPropTypes";
24+
import type { GridLayoutProps } from "./gridLayoutPropTypes";
2525
import { GridLines } from "./gridLines";
2626
import { changeItemOp, deleteItemOp, LayoutOp, renameItemOp } from "./layoutOp";
2727
import { getUILayout, LayoutOps, layoutOpUtils } from "./layoutOpUtils";
@@ -1102,7 +1102,7 @@ const LayoutContainer = styled.div<{
11021102
}`}
11031103
`;
11041104

1105-
export const ReactGridLayout = React.memo(GridLayout);
1105+
export const ReactGridLayout = React.memo(GridLayout, (prev, next) => isEqual(prev, next));
11061106

11071107
function moveOrResize(
11081108
e: React.KeyboardEvent,

client/packages/lowcoder/src/layout/gridLines.tsx

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { CSSProperties } from "react";
22
import { calcGridColWidth, PositionParams } from "./calculateUtils";
33
import { Position, setTransform } from "./utils";
4+
import React from "react";
45

56
interface GridLineProps {
67
position: Position;
@@ -19,10 +20,10 @@ function setBackgroundProps(positionParams: PositionParams, lineColor: string):
1920
};
2021
}
2122

22-
export function GridLines(props: GridLineProps) {
23+
export const GridLines = React.memo((props: GridLineProps) => {
2324
const style = {
2425
...setTransform(props.position),
2526
...setBackgroundProps(props.positionParams, props.lineColor),
2627
};
2728
return <div style={style} />;
28-
}
29+
})

client/packages/lowcoder/src/layout/layoutOpUtils.tsx

+4
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ export namespace layoutOpUtils {
9292
}
9393

9494
function reduce(layout: Layout, op: LayoutOp, stickyItemMap?: Record<string, Set<string>>): Layout {
95+
// console.log(op.type);
9596
let newLayout = layout;
9697
switch (op.type) {
9798
case LayoutOpTypes.CHANGE_ITEM: {
@@ -146,6 +147,7 @@ export let getUILayout = (
146147
ops: LayoutOps | undefined,
147148
setHiddenCompHeightZero: boolean = false
148149
): Layout => {
150+
// console.log('layout->before', changedHs, layout);
149151
// log.log("getUILayout. layout: ", layout, " extraLayout: ", extraLayout, " changedHs: ", changedHs, " ops: ", ops);
150152
const stickyItemMap = getStickyItemMap(layout);
151153
const hiddenItemHeight = _.fromPairs(
@@ -163,7 +165,9 @@ export let getUILayout = (
163165
realOps.forEach((op) => {
164166
layout = reduce(layout, op, stickyItemMap);
165167
});
168+
// console.log('layout->after', layout);
166169
layout = cascade(layout);
170+
// console.log('layout->after->2', layout);
167171
if (!setHiddenCompHeightZero) {
168172
const recoverHiddenOps = _.toPairs(hiddenItemHeight).map(([i, h]) => changeItemOp(i, { h }));
169173
recoverHiddenOps.forEach((op) => {

client/packages/lowcoder/src/layout/utils.ts

+1
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,7 @@ export function setTransform(
207207
hidden?: boolean,
208208
isDragging?: boolean,
209209
): Record<string, any> {
210+
console.log(name, {top, left, width, height })
210211
// Replace unitless items with px
211212
const translate = `translate(${left}px,${top}px)`;
212213
function containsChart(str:string) {

0 commit comments

Comments
 (0)