Skip to content

Commit 1af35d0

Browse files
optimise modal comp
1 parent 03e9839 commit 1af35d0

File tree

2 files changed

+109
-44
lines changed

2 files changed

+109
-44
lines changed

client/packages/lowcoder/src/comps/hooks/hookComp.tsx

Lines changed: 30 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ import _ from "lodash";
2727
import dayjs from "dayjs";
2828
import { ConstructorToComp } from "lowcoder-core";
2929
import { ScrollBar, Section, sectionNames } from "lowcoder-design";
30-
import React, { useContext, useEffect, useMemo } from "react";
30+
import React, { useContext, useEffect, useMemo, useCallback } from "react";
3131
import { useInterval, useTitle, useWindowSize } from "react-use";
3232
import { useCurrentUser } from "util/currentUser";
3333
import { LocalStorageComp } from "./localStorageComp";
@@ -53,9 +53,16 @@ const CurrentUserHookComp = hookToStateComp(() => {
5353

5454
function useCurrentTime() {
5555
const [time, setTime] = React.useState(0);
56-
useInterval(() => {
57-
setTime(new Date().getTime());
58-
}, 1000);
56+
57+
// Add cleanup for the interval
58+
useEffect(() => {
59+
const interval = setInterval(() => {
60+
setTime(new Date().getTime());
61+
}, 1000);
62+
63+
return () => clearInterval(interval);
64+
}, []);
65+
5966
return useMemo(
6067
() => ({
6168
time: time,
@@ -126,6 +133,23 @@ function SelectHookView(props: {
126133
const editorState = useContext(EditorContext);
127134
const selectedComp = editorState.selectedComp();
128135

136+
// Memoize the comp tree calculation
137+
const compTree = useMemo(() => {
138+
if (!props.comp || !(props.comp as any).getCompTree) return null;
139+
return (props.comp as any).getCompTree();
140+
}, [props.comp]);
141+
142+
// Memoize the child components calculation
143+
const allChildComp = useMemo(() => {
144+
if (!compTree) return {};
145+
return getAllCompItems(compTree);
146+
}, [compTree]);
147+
148+
// Memoize the click handler
149+
const handleClick = useCallback(() => {
150+
editorState.setSelectedCompNames(new Set([props.compName]));
151+
}, [editorState, props.compName]);
152+
129153
// Select the modal and its subcomponents on the left to display the modal
130154
useEffect(() => {
131155
if (
@@ -151,7 +175,6 @@ function SelectHookView(props: {
151175
);
152176
} else {
153177
// all child components of modal
154-
const allChildComp = getAllCompItems((props.comp as any).getCompTree());
155178
const selectChildComp = Object.values(allChildComp).find(
156179
(child) => child === selectedComp
157180
);
@@ -166,14 +189,10 @@ function SelectHookView(props: {
166189
);
167190
}
168191
}
169-
}, [selectedComp, editorState.selectSource]);
192+
}, [selectedComp, editorState.selectSource, allChildComp]);
170193

171194
return (
172-
<div
173-
onClick={() =>
174-
editorState.setSelectedCompNames(new Set([props.compName]))
175-
}
176-
>
195+
<div onClick={handleClick}>
177196
{props.children}
178197
</div>
179198
);

client/packages/lowcoder/src/comps/hooks/modalComp.tsx

Lines changed: 79 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import { Layers } from "constants/Layers";
1414
import { HintPlaceHolder, Modal, Section, sectionNames } from "lowcoder-design";
1515
import { trans } from "i18n";
1616
import { changeChildAction } from "lowcoder-core";
17-
import { CSSProperties, useCallback } from "react";
17+
import { CSSProperties, useCallback, useMemo, useRef } from "react";
1818
import { ResizeHandle } from "react-resizable";
1919
import styled, { css } from "styled-components";
2020
import { useUserViewMode } from "util/hooks";
@@ -116,19 +116,36 @@ let TmpModalComp = (function () {
116116
(props, dispatch) => {
117117
const userViewMode = useUserViewMode();
118118
const appID = useApplicationId();
119-
const bodyStyle: CSSProperties = { padding: 0 };
120-
const width = transToPxSize(props.width || DEFAULT_WIDTH);
121-
let height = undefined;
122-
let resizeHandles: ResizeHandle[] = ["w", "e"];
123-
if (!props.autoHeight) {
124-
height = transToPxSize(props.height || DEFAULT_HEIGHT);
125-
resizeHandles.push("s");
126-
bodyStyle.overflow = "hidden auto";
127-
}
128-
if (userViewMode) {
129-
resizeHandles = [];
130-
}
131-
const { items, ...otherContainerProps } = props.container;
119+
const containerRef = useRef<HTMLElement | null>(null);
120+
121+
// Memoize body style
122+
const bodyStyle = useMemo<CSSProperties>(() => ({
123+
padding: 0,
124+
overflow: props.autoHeight ? undefined : "hidden auto"
125+
}), [props.autoHeight]);
126+
127+
// Memoize width and height
128+
const width = useMemo(() =>
129+
transToPxSize(props.width || DEFAULT_WIDTH),
130+
[props.width]
131+
);
132+
133+
const height = useMemo(() =>
134+
!props.autoHeight ? transToPxSize(props.height || DEFAULT_HEIGHT) : undefined,
135+
[props.autoHeight, props.height]
136+
);
137+
138+
// Memoize resize handles
139+
const resizeHandles = useMemo<ResizeHandle[]>(() => {
140+
if (userViewMode) return [];
141+
const handles: ResizeHandle[] = ["w", "e"];
142+
if (!props.autoHeight) {
143+
handles.push("s");
144+
}
145+
return handles;
146+
}, [userViewMode, props.autoHeight]);
147+
148+
// Memoize resize handler
132149
const onResizeStop = useCallback(
133150
(
134151
e: React.SyntheticEvent,
@@ -144,13 +161,48 @@ let TmpModalComp = (function () {
144161
},
145162
[dispatch]
146163
);
147-
let paddingValues = [10, 10];
148-
if (props.style.padding != undefined) {
164+
165+
// Memoize padding values
166+
const paddingValues = useMemo(() => {
167+
if (!props.style.padding) return [10, 10];
149168
const extractedValues = extractMarginValues(props.style);
150-
if (extractedValues !== null) {
151-
paddingValues = extractedValues;
152-
}
153-
}
169+
return extractedValues || [10, 10];
170+
}, [props.style.padding]);
171+
172+
// Memoize container getter
173+
const getContainer = useCallback(() => {
174+
if (!containerRef.current) {
175+
containerRef.current = document.querySelector(`#${CanvasContainerID}`) || document.body;
176+
}
177+
return containerRef.current;
178+
}, []);
179+
180+
// Memoize event handlers
181+
const handleCancel = useCallback((e: React.MouseEvent) => {
182+
if (props.toggleClose) {
183+
props.visible.onChange(false);
184+
}
185+
}, [props.toggleClose, props.visible]);
186+
187+
const handleAfterClose = useCallback(() => {
188+
if (props.toggleClose) {
189+
props.onEvent("close");
190+
}
191+
}, [props.toggleClose, props.onEvent]);
192+
193+
const handleAfterOpenChange = useCallback((open: boolean) => {
194+
if (open) {
195+
props.onEvent("open");
196+
}
197+
}, [props.onEvent]);
198+
199+
// Memoize modal render function
200+
const modalRender = useCallback((node: React.ReactNode) => (
201+
<ModalStyled $style={props.style} $modalScrollbar={props.modalScrollbar}>
202+
{node}
203+
</ModalStyled>
204+
), [props.style, props.modalScrollbar]);
205+
154206
return (
155207
<BackgroundColorContext.Provider value={props.style.background}>
156208
<ModalWrapper>
@@ -162,30 +214,24 @@ let TmpModalComp = (function () {
162214
open={props.visible.value}
163215
maskClosable={props.maskClosable}
164216
focusTriggerAfterClose={false}
165-
getContainer={() => document.querySelector(`#${CanvasContainerID}`) || document.body}
217+
getContainer={getContainer}
166218
footer={null}
167219
styles={{body: bodyStyle}}
168220
title={props.title}
169221
$titleAlign={props.titleAlign}
170222
width={width}
171-
onCancel={(e) => {
172-
props.toggleClose&&props.visible.onChange(false);
173-
}}
174-
afterClose={() => {
175-
props.toggleClose&&props.onEvent("close");
176-
}}
177-
afterOpenChange={(open: boolean) => {
178-
if (open) props.onEvent("open");
179-
}}
223+
onCancel={handleCancel}
224+
afterClose={handleAfterClose}
225+
afterOpenChange={handleAfterOpenChange}
180226
zIndex={Layers.modal}
181-
modalRender={(node) => <ModalStyled $style={props.style} $modalScrollbar={props.modalScrollbar}>{node}</ModalStyled>}
227+
modalRender={modalRender}
182228
mask={props.showMask}
183229
className={clsx(`app-${appID}`, props.className)}
184230
data-testid={props.dataTestId as string}
185231
>
186232
<InnerGrid
187-
{...otherContainerProps}
188-
items={gridItemCompToGridItems(items)}
233+
{...props.container}
234+
items={gridItemCompToGridItems(props.container.items)}
189235
horizontalGridCells={props.horizontalGridCells}
190236
autoHeight={props.autoHeight}
191237
minHeight={paddingValues ? DEFAULT_HEIGHT - paddingValues[0] * 2 + "px" : ""}

0 commit comments

Comments
 (0)