Skip to content

Commit f588333

Browse files
authoredSep 8, 2024··
Merge pull request #1147 from lowcoder-org/minimize-rerendering
Minimize rerendering
2 parents 1e3d6a6 + 0bf1805 commit f588333

File tree

19 files changed

+438
-251
lines changed

19 files changed

+438
-251
lines changed
 

‎client/packages/lowcoder/src/components/PermissionDialog/AppPermissionDialog.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ import { SHARE_TITLE } from "../../constants/apiConstants";
3131
import { messageInstance } from "lowcoder-design/src/components/GlobalInstances";
3232
import { default as Divider } from "antd/es/divider";
3333

34-
export const AppPermissionDialog = (props: {
34+
export const AppPermissionDialog = React.memo((props: {
3535
applicationId: string;
3636
visible: boolean;
3737
onVisibleChange: (visible: boolean) => void;
@@ -148,7 +148,7 @@ export const AppPermissionDialog = (props: {
148148
}
149149
/>
150150
);
151-
};
151+
});
152152

153153
const InviteInputBtn = styled.div`
154154
display: flex;

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

+23-13
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ import {
2424
DEFAULT_GRID_COLUMNS,
2525
DEFAULT_ROW_HEIGHT,
2626
} from "layout/calculateUtils";
27-
import _ from "lodash";
27+
import _, { isEqual } from "lodash";
2828
import {
2929
ActionExtraInfo,
3030
changeChildAction,
@@ -313,7 +313,7 @@ const ItemWrapper = styled.div<{ $disableInteract?: boolean }>`
313313
pointer-events: ${(props) => (props.$disableInteract ? "none" : "unset")};
314314
`;
315315

316-
const GridItemWrapper = React.forwardRef(
316+
const GridItemWrapper = React.memo(React.forwardRef(
317317
(
318318
props: React.PropsWithChildren<HTMLAttributes<HTMLDivElement>>,
319319
ref: React.ForwardedRef<HTMLDivElement>
@@ -326,11 +326,11 @@ const GridItemWrapper = React.forwardRef(
326326
</ItemWrapper>
327327
);
328328
}
329-
);
329+
));
330330

331331
type GirdItemViewRecord = Record<string, GridItem>;
332332

333-
export function InnerGrid(props: ViewPropsWithSelect) {
333+
export const InnerGrid = React.memo((props: ViewPropsWithSelect) => {
334334
const {
335335
positionParams,
336336
rowCount = Infinity,
@@ -348,11 +348,13 @@ export function InnerGrid(props: ViewPropsWithSelect) {
348348

349349
// Falk: TODO: Here we can define the inner grid columns dynamically
350350
//Added By Aqib Mirza
351-
const defaultGrid =
352-
horizontalGridCells ||
351+
const defaultGrid = useMemo(() => {
352+
return horizontalGridCells ||
353353
currentTheme?.gridColumns ||
354354
defaultTheme?.gridColumns ||
355355
"12";
356+
}, [horizontalGridCells, currentTheme?.gridColumns, defaultTheme?.gridColumns]);
357+
356358
/////////////////////
357359
const isDroppable =
358360
useContext(IsDroppable) && (_.isNil(props.isDroppable) || props.isDroppable) && !readOnly;
@@ -385,7 +387,7 @@ export function InnerGrid(props: ViewPropsWithSelect) {
385387

386388
const canAddSelect = useMemo(
387389
() => _.size(containerSelectNames) === _.size(editorState.selectedCompNames),
388-
[containerSelectNames, editorState]
390+
[containerSelectNames, editorState.selectedCompNames]
389391
);
390392

391393
const dispatchPositionParamsTimerRef = useRef(0);
@@ -432,16 +434,21 @@ export function InnerGrid(props: ViewPropsWithSelect) {
432434
onPositionParamsChange,
433435
onRowCountChange,
434436
positionParams,
435-
props,
437+
props.dispatch,
438+
props.containerPadding,
436439
]
437440
);
438441
const setSelectedNames = useCallback(
439442
(names: Set<string>) => {
440443
editorState.setSelectedCompNames(names);
441444
},
442-
[editorState]
445+
[editorState.setSelectedCompNames]
443446
);
444-
const { width, ref } = useResizeDetector({ onResize, handleHeight: isRowCountLocked });
447+
448+
const { width, ref } = useResizeDetector({
449+
onResize,
450+
handleHeight: isRowCountLocked,
451+
});
445452

446453
const itemViewRef = useRef<GirdItemViewRecord>({});
447454
const itemViews = useMemo(() => {
@@ -464,9 +471,10 @@ export function InnerGrid(props: ViewPropsWithSelect) {
464471
const clickItem = useCallback(
465472
(
466473
e: React.MouseEvent<HTMLDivElement,
467-
globalThis.MouseEvent>, name: string
474+
globalThis.MouseEvent>,
475+
name: string,
468476
) => selectItem(e, name, canAddSelect, containerSelectNames, setSelectedNames),
469-
[canAddSelect, containerSelectNames, setSelectedNames]
477+
[selectItem, canAddSelect, containerSelectNames, setSelectedNames]
470478
);
471479

472480
useEffect(() => {
@@ -555,7 +563,9 @@ export function InnerGrid(props: ViewPropsWithSelect) {
555563
{itemViews}
556564
</ReactGridLayout>
557565
);
558-
}
566+
}, (prevProps, newProps) => {
567+
return isEqual(prevProps, newProps);
568+
});
559569

560570
function selectItem(
561571
e: MouseEvent<HTMLDivElement>,

‎client/packages/lowcoder/src/comps/comps/gridLayoutComp/canvasView.tsx

+6-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { EditorContext } from "comps/editorState";
22
import { EditorContainer } from "pages/common/styledComponent";
3-
import { Profiler, useContext, useRef, useState } from "react";
3+
import React, { Profiler, useContext, useRef, useState } from "react";
44
import styled from "styled-components";
55
import { profilerCallback } from "util/cacheUtils";
66
import {
@@ -20,6 +20,7 @@ import { CanvasContainerID } from "constants/domLocators";
2020
import { CNRootContainer } from "constants/styleSelectors";
2121
import { ScrollBar } from "lowcoder-design";
2222
import { defaultTheme } from "@lowcoder-ee/constants/themeConstants";
23+
import { isEqual } from "lodash";
2324

2425
// min-height: 100vh;
2526

@@ -72,7 +73,7 @@ function getDragSelectedNames(
7273

7374
const EmptySet = new Set<string>();
7475

75-
export function CanvasView(props: ContainerBaseProps) {
76+
export const CanvasView = React.memo((props: ContainerBaseProps) => {
7677
const editorState = useContext(EditorContext);
7778
const [dragSelectedComps, setDragSelectedComp] = useState(EmptySet);
7879
const scrollContainerRef = useRef(null);
@@ -166,4 +167,6 @@ export function CanvasView(props: ContainerBaseProps) {
166167
</EditorContainer>
167168
</CanvasContainer>
168169
);
169-
}
170+
}, (prevProps, newProps) => {
171+
return isEqual(prevProps, newProps);
172+
});

‎client/packages/lowcoder/src/comps/comps/gridLayoutComp/dragSelector.tsx

+3-1
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ const InitialState = {
3838
startPoint: undefined,
3939
};
4040

41-
export class DragSelector extends React.Component<SectionProps, SectionState> {
41+
class DragSelectorComp extends React.Component<SectionProps, SectionState> {
4242
private readonly selectAreaRef: React.RefObject<HTMLDivElement>;
4343

4444
constructor(props: SectionProps) {
@@ -178,3 +178,5 @@ export class DragSelector extends React.Component<SectionProps, SectionState> {
178178
};
179179
}
180180
}
181+
182+
export const DragSelector = React.memo(DragSelectorComp);

‎client/packages/lowcoder/src/comps/comps/rootComp.tsx

+6-2
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ import {
3232
import RefTreeComp from "./refTreeComp";
3333
import { ExternalEditorContext } from "util/context/ExternalEditorContext";
3434
import { useUserViewMode } from "util/hooks";
35+
import React from "react";
36+
import { isEqual } from "lodash";
3537

3638
const EditorView = lazy(
3739
() => import("pages/editor/editorView"),
@@ -55,7 +57,7 @@ const childrenMap = {
5557
preload: PreloadComp,
5658
};
5759

58-
function RootView(props: RootViewProps) {
60+
const RootView = React.memo((props: RootViewProps) => {
5961
const previewTheme = useContext(ThemeContext);
6062
const { comp, isModuleRoot, ...divProps } = props;
6163
const [editorState, setEditorState] = useState<EditorState>();
@@ -143,7 +145,9 @@ function RootView(props: RootViewProps) {
143145
</PropertySectionContext.Provider>
144146
</div>
145147
);
146-
}
148+
}, (prevProps, nextProps) => {
149+
return isEqual(prevProps, nextProps);
150+
});
147151

148152
/**
149153
* Root Comp

‎client/packages/lowcoder/src/comps/generators/uiCompBuilder.tsx

+10-11
Original file line numberDiff line numberDiff line change
@@ -44,10 +44,10 @@ export type NewChildren<ChildrenCompMap extends Record<string, Comp<unknown>>> =
4444
version: InstanceType<typeof StringControl>;
4545
};
4646

47-
export function HidableView(props: {
47+
export const HidableView = React.memo((props: {
4848
children: JSX.Element | React.ReactNode;
4949
hidden: boolean;
50-
}) {
50+
}) => {
5151
const { readOnly } = useContext(ExternalEditorContext);
5252
if (readOnly) {
5353
return <>{props.children}</>;
@@ -64,15 +64,15 @@ export function HidableView(props: {
6464
</>
6565
);
6666
}
67-
}
67+
})
6868

69-
export function ExtendedPropertyView<
69+
export const ExtendedPropertyView = React.memo(<
7070
ChildrenCompMap extends Record<string, Comp<unknown>>,
7171
>(props: {
7272
children: JSX.Element | React.ReactNode,
7373
childrenMap: NewChildren<ChildrenCompMap>
7474
}
75-
) {
75+
) => {
7676
const [compVersions, setCompVersions] = useState(['latest']);
7777
const [compName, setCompName] = useState('');
7878
const editorState = useContext(EditorContext);
@@ -129,7 +129,7 @@ export function ExtendedPropertyView<
129129
)}
130130
</>
131131
);
132-
}
132+
});
133133

134134
export function uiChildren<
135135
ChildrenCompMap extends Record<string, Comp<unknown>>,
@@ -275,11 +275,11 @@ export const DisabledContext = React.createContext<boolean>(false);
275275
/**
276276
* Guaranteed to be in a react component, so that react hooks can be used internally
277277
*/
278-
function UIView(props: {
278+
const UIView = React.memo((props: {
279279
innerRef: React.RefObject<HTMLDivElement>;
280280
comp: any;
281281
viewFn: any;
282-
}) {
282+
}) => {
283283
const comp = props.comp;
284284
const childrenProps = childrenToProps(comp.children);
285285
const childrenJsonProps = comp.toJsonValue();
@@ -397,13 +397,12 @@ function UIView(props: {
397397
width: '100%',
398398
height: '100%',
399399
margin: '0px',
400-
padding:getPadding()
401-
400+
padding: getPadding()
402401
}}
403402
>
404403
<HidableView hidden={childrenProps.hidden as boolean}>
405404
{props.viewFn(childrenProps, comp.dispatch)}
406405
</HidableView>
407406
</div>
408407
);
409-
}
408+
});

‎client/packages/lowcoder/src/index.sdk.ts

+6
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,13 @@ import * as styledNameExports from "styled-components";
66
import styledDefault from "styled-components";
77
export * as styledm from "styled-components";
88
export * from "comps/comps/containerBase/containerCompBuilder";
9+
export * from "comps/comps/containerBase/iContainer";
10+
export * from "comps/comps/containerBase/utils";
11+
export * from "comps/comps/containerBase/simpleContainerComp";
912
export * from "comps/utils/backgroundColorContext";
1013
export { getData } from "comps/comps/listViewComp/listViewUtils";
1114
export { gridItemCompToGridItems, InnerGrid } from "comps/comps/containerComp/containerView";
15+
export type { ContainerBaseProps } from "comps/comps/containerComp/containerView";
1216

1317
export { Layers } from "constants/Layers";
1418
export * from "comps/controls/eventHandlerControl";
@@ -97,6 +101,7 @@ export * from "comps/controls/simpleStringControl";
97101
export * from "comps/controls/stringSimpleControl";
98102
export * from "comps/controls/styleControl";
99103
export * from "comps/controls/styleControlConstants";
104+
export * from "comps/controls/slotControl";
100105

101106
// generators
102107
export * from "comps/generators/changeDataType";
@@ -114,6 +119,7 @@ export * from "comps/generators/withExposing";
114119
export * from "comps/generators/withIsLoading";
115120
export * from "comps/generators/withMethodExposing";
116121
export * from "comps/generators/withType";
122+
export * from "comps/generators/controlCompBuilder";
117123

118124
export * from "appView/bootstrapAt";
119125
export * from "appView/LowcoderAppView";

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

+2-2
Original file line numberDiff line numberDiff line change
@@ -231,7 +231,7 @@ const HiddenIcon = styled(CloseEyeIcon)`
231231
}
232232
`;
233233

234-
export const CompSelectionWrapper = (props: {
234+
export const CompSelectionWrapper = React.memo((props: {
235235
id?: string;
236236
compType: UICompType;
237237
className?: string;
@@ -376,4 +376,4 @@ export const CompSelectionWrapper = (props: {
376376
</SelectableDiv>
377377
</div>
378378
);
379-
};
379+
});

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

+273-137
Large diffs are not rendered by default.

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

+8-6
Original file line numberDiff line numberDiff line change
@@ -471,16 +471,16 @@ class GridLayout extends React.Component<GridLayoutProps, GridLayoutState> {
471471
isDraggable={isDraggable && isItemDraggable(item)}
472472
isResizable={isResizable && isItemResizable(item)}
473473
isSelectable={selectable}
474-
transformScale={transformScale}
474+
transformScale={transformScale || 1}
475475
w={item.w}
476476
h={extraItem?.hidden && !extraItem?.isSelected ? 0 : item.h}
477477
x={item.x}
478478
y={item.y}
479479
i={item.i}
480-
minH={item.minH}
481-
minW={item.minW}
482-
maxH={item.maxH}
483-
maxW={item.maxW}
480+
minH={item.minH || 1}
481+
minW={item.minW || 1}
482+
maxH={item.maxH || Infinity}
483+
maxW={item.maxW || Infinity}
484484
placeholder={item.placeholder}
485485
layoutHide={item.hide}
486486
static={item.static}
@@ -496,6 +496,7 @@ class GridLayout extends React.Component<GridLayoutProps, GridLayoutState> {
496496
bottom: (showName?.bottom ?? 0) + (this.ref.current?.scrollHeight ?? 0),
497497
}}
498498
zIndex={zIndex}
499+
className=""
499500
>
500501
{child}
501502
</GridItem>
@@ -1096,7 +1097,8 @@ const LayoutContainer = styled.div<{
10961097
}`}
10971098
`;
10981099

1099-
export const ReactGridLayout = GridLayout;
1100+
// export const ReactGridLayout = React.memo(GridLayout);
1101+
export const ReactGridLayout = React.memo(GridLayout);
11001102

11011103
function moveOrResize(
11021104
e: React.KeyboardEvent,

‎client/packages/lowcoder/src/pages/common/header.tsx

+66-59
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ import {
2525
} from "lowcoder-design";
2626
import { trans } from "i18n";
2727
import dayjs from "dayjs";
28-
import { useContext, useState } from "react";
28+
import { useContext, useEffect, useMemo, useState } from "react";
2929
import { useDispatch, useSelector } from "react-redux";
3030
import {
3131
publishApplication,
@@ -453,67 +453,74 @@ export default function Header(props: HeaderProps) {
453453
</>
454454
);
455455

456-
const headerEnd = showAppSnapshot ? (
457-
<HeaderProfile user={user} />
458-
) : (
459-
<>
460-
{applicationId && (
461-
<AppPermissionDialog
462-
applicationId={applicationId}
463-
visible={permissionDialogVisible}
464-
onVisibleChange={(visible) =>
465-
!visible && setPermissionDialogVisible(false)
466-
}
467-
/>
468-
)}
469-
{canManageApp(user, application) && (
470-
<GrayBtn onClick={() => setPermissionDialogVisible(true)}>
471-
{SHARE_TITLE}
472-
</GrayBtn>
473-
)}
474-
<PreviewBtn buttonType="primary" onClick={() => preview(applicationId)}>
475-
{trans("header.preview")}
476-
</PreviewBtn>
477-
478-
<Dropdown
479-
className="cypress-header-dropdown"
480-
placement="bottomRight"
481-
trigger={["click"]}
482-
dropdownRender={() => (
483-
<DropdownMenuStyled
484-
style={{ minWidth: "110px", borderRadius: "4px" }}
485-
onClick={(e) => {
486-
if (e.key === "deploy") {
487-
dispatch(publishApplication({ applicationId }));
488-
} else if (e.key === "snapshot") {
489-
dispatch(setShowAppSnapshot(true));
490-
}
491-
}}
492-
items={[
493-
{
494-
key: "deploy",
495-
label: (
496-
<CommonTextLabel>{trans("header.deploy")}</CommonTextLabel>
497-
),
498-
},
499-
{
500-
key: "snapshot",
501-
label: (
502-
<CommonTextLabel>{trans("header.snapshot")}</CommonTextLabel>
503-
),
504-
},
505-
]}
456+
const headerEnd = useMemo(() => {
457+
return showAppSnapshot ? (
458+
<HeaderProfile user={user} />
459+
) : (
460+
<>
461+
{applicationId && (
462+
<AppPermissionDialog
463+
applicationId={applicationId}
464+
visible={permissionDialogVisible}
465+
onVisibleChange={(visible) =>
466+
!visible && setPermissionDialogVisible(false)
467+
}
506468
/>
507469
)}
508-
>
509-
<PackUpBtn buttonType="primary">
510-
<PackUpIcon />
511-
</PackUpBtn>
512-
</Dropdown>
470+
{canManageApp(user, application) && (
471+
<GrayBtn onClick={() => setPermissionDialogVisible(true)}>
472+
{SHARE_TITLE}
473+
</GrayBtn>
474+
)}
475+
<PreviewBtn buttonType="primary" onClick={() => preview(applicationId)}>
476+
{trans("header.preview")}
477+
</PreviewBtn>
478+
479+
<Dropdown
480+
className="cypress-header-dropdown"
481+
placement="bottomRight"
482+
trigger={["click"]}
483+
dropdownRender={() => (
484+
<DropdownMenuStyled
485+
style={{ minWidth: "110px", borderRadius: "4px" }}
486+
onClick={(e) => {
487+
if (e.key === "deploy") {
488+
dispatch(publishApplication({ applicationId }));
489+
} else if (e.key === "snapshot") {
490+
dispatch(setShowAppSnapshot(true));
491+
}
492+
}}
493+
items={[
494+
{
495+
key: "deploy",
496+
label: (
497+
<CommonTextLabel>{trans("header.deploy")}</CommonTextLabel>
498+
),
499+
},
500+
{
501+
key: "snapshot",
502+
label: (
503+
<CommonTextLabel>{trans("header.snapshot")}</CommonTextLabel>
504+
),
505+
},
506+
]}
507+
/>
508+
)}
509+
>
510+
<PackUpBtn buttonType="primary">
511+
<PackUpIcon />
512+
</PackUpBtn>
513+
</Dropdown>
513514

514-
<HeaderProfile user={user} />
515-
</>
516-
);
515+
<HeaderProfile user={user} />
516+
</>
517+
);
518+
}, [
519+
user,
520+
showAppSnapshot,
521+
applicationId,
522+
permissionDialogVisible,
523+
]);
517524

518525
return (
519526
<LayoutHeader

‎client/packages/lowcoder/src/pages/common/help.tsx

+3-1
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,7 @@ const introVideoUrl = trans("docUrls.introVideo");
181181
const issueUrl = trans("lowcoderUrl.createIssue");
182182
const discordUrl = trans("lowcoderUrl.discord");
183183

184-
export function HelpDropdown(props: HelpDropdownProps) {
184+
function HelpDropdownComp(props: HelpDropdownProps) {
185185
const [showHelp, setShowHelp] = useState(true);
186186
const [version, setVersion] = useState("");
187187
const dispatch = useDispatch();
@@ -446,3 +446,5 @@ export function HelpDropdown(props: HelpDropdownProps) {
446446
</HelpWrapper>
447447
</>);
448448
}
449+
450+
export const HelpDropdown = React.memo(HelpDropdownComp);

‎client/packages/lowcoder/src/pages/common/previewHeader.tsx

+4-1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import { getBrandingConfig } from "../../redux/selectors/configSelectors";
2020
import { HeaderStartDropdown } from "./headerStartDropdown";
2121
import { useParams } from "react-router";
2222
import { AppPathParams } from "constants/applicationConstants";
23+
import React from "react";
2324

2425
const HeaderFont = styled.div<{ $bgColor: string }>`
2526
font-weight: 500;
@@ -127,7 +128,7 @@ export function HeaderProfile(props: { user: User }) {
127128
);
128129
}
129130

130-
export const PreviewHeader = () => {
131+
const PreviewHeaderComp = () => {
131132
const params = useParams<AppPathParams>();
132133
const user = useSelector(getUser);
133134
const application = useSelector(currentApplication);
@@ -203,3 +204,5 @@ export const PreviewHeader = () => {
203204
/>
204205
);
205206
};
207+
208+
export const PreviewHeader = React.memo(PreviewHeaderComp);

‎client/packages/lowcoder/src/pages/editor/appEditorInternal.tsx

+6-2
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ import { useUserViewMode } from "../../util/hooks";
2424
import { QueryApi } from "api/queryApi";
2525
import { RootCompInstanceType } from "./useRootCompInstance";
2626
import { getCurrentUser } from "redux/selectors/usersSelectors";
27+
import React from "react";
28+
import { isEqual } from "lodash";
2729

2830
/**
2931
* FIXME: optimize the logic of saving comps
@@ -77,7 +79,7 @@ interface AppEditorInternalViewProps {
7779
compInstance: RootCompInstanceType;
7880
}
7981

80-
export function AppEditorInternalView(props: AppEditorInternalViewProps) {
82+
export const AppEditorInternalView = React.memo((props: AppEditorInternalViewProps) => {
8183
const isUserViewMode = useUserViewMode();
8284
const extraExternalEditorState = useSelector(getExternalEditorState);
8385
const dispatch = useDispatch();
@@ -125,4 +127,6 @@ export function AppEditorInternalView(props: AppEditorInternalViewProps) {
125127
</ExternalEditorContext.Provider>
126128
</ConfigProvider>
127129
);
128-
}
130+
}, (prevProps, nextProps) => {
131+
return isEqual(prevProps, nextProps)
132+
});

‎client/packages/lowcoder/src/pages/editor/editorHotKeys.tsx

+6-6
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ function handleMouseDown(e: MouseEvent, editorState: EditorState, showLeftPanel:
113113
}
114114
}
115115

116-
export function EditorGlobalHotKeys(props: GlobalProps) {
116+
export const EditorGlobalHotKeys = React.memo((props: GlobalProps) => {
117117
const editorState = useContext(EditorContext);
118118
const { history: editorHistory } = useContext(ExternalEditorContext);
119119
const { togglePanel, panelStatus, toggleShortcutList } = props;
@@ -155,7 +155,7 @@ export function EditorGlobalHotKeys(props: GlobalProps) {
155155
children={props.children}
156156
/>
157157
);
158-
}
158+
})
159159

160160
// local hotkeys
161161
function handleEditorKeyDown(e: React.KeyboardEvent, editorState: EditorState) {
@@ -186,7 +186,7 @@ function handleEditorKeyDown(e: React.KeyboardEvent, editorState: EditorState) {
186186
}
187187
}
188188

189-
export function EditorHotKeys(props: Props) {
189+
export const EditorHotKeys = React.memo((props: Props) => {
190190
const editorState = useContext(EditorContext);
191191
const onKeyDown = useCallback(
192192
(e: React.KeyboardEvent) => handleEditorKeyDown(e, editorState),
@@ -200,9 +200,9 @@ export function EditorHotKeys(props: Props) {
200200
children={props.children}
201201
/>
202202
);
203-
}
203+
})
204204

205-
export function CustomShortcutWrapper(props: { children: React.ReactNode }) {
205+
export const CustomShortcutWrapper = React.memo((props: { children: React.ReactNode }) => {
206206
const editorState = useContext(EditorContext);
207207
const handleCustomShortcut = useCallback(
208208
(e: KeyboardEvent) => {
@@ -215,4 +215,4 @@ export function CustomShortcutWrapper(props: { children: React.ReactNode }) {
215215
{props.children}
216216
</GlobalShortcutsWrapper>
217217
);
218-
}
218+
})

‎client/packages/lowcoder/src/pages/editor/editorSkeletonView.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -60,12 +60,12 @@ export default function EditorSkeletonView() {
6060
return (
6161
<>
6262
<Height100Div>
63-
<Header
63+
{/* <Header
6464
panelStatus={panelStatus}
6565
togglePanel={_.noop}
6666
editorModeStatus={editorModeStatus}
6767
toggleEditorModeStatus={_.noop}
68-
/>
68+
/> */}
6969
<Body>
7070
<SiderStyled />
7171
{panelStatus.left && (

‎client/packages/lowcoder/src/pages/editor/editorView.tsx

+4-1
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ import {
5454
import { isAggregationApp } from "util/appUtils";
5555
import EditorSkeletonView from "./editorSkeletonView";
5656
import { getCommonSettings } from "@lowcoder-ee/redux/selectors/commonSettingSelectors";
57+
import { isEqual } from "lodash";
5758

5859
const LeftContent = lazy(
5960
() => import('./LeftContent')
@@ -577,4 +578,6 @@ function EditorView(props: EditorViewProps) {
577578
);
578579
}
579580

580-
export default EditorView;
581+
export default React.memo(EditorView, (prevProps, newProps) => {
582+
return isEqual(prevProps, newProps);
583+
});

‎client/packages/lowcoder/src/pages/editor/right/RightPanel.tsx

+4-1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import { AttributeIcon } from "lowcoder-design";
99
import { InsertIcon } from "lowcoder-design";
1010
import { trans } from "i18n";
1111
import { isAggregationApp } from "util/appUtils";
12+
import React from "react";
1213

1314
type RightPanelProps = {
1415
onTabChange: (key: string) => void;
@@ -17,7 +18,7 @@ type RightPanelProps = {
1718
uiComp?: InstanceType<typeof UIComp>;
1819
};
1920

20-
export default function RightPanel(props: RightPanelProps) {
21+
function RightPanel(props: RightPanelProps) {
2122
const { onTabChange, showPropertyPane, uiComp } = props;
2223
const uiCompType = uiComp && (uiComp.children.compType.getView() as UiLayoutType);
2324
const aggregationApp = uiCompType && isAggregationApp(uiCompType);
@@ -55,3 +56,5 @@ export default function RightPanel(props: RightPanelProps) {
5556
</RightPanelWrapper>
5657
);
5758
}
59+
60+
export default React.memo(RightPanel);

‎client/packages/lowcoder/src/pages/tutorials/editorTutorials.tsx

+4-1
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ import { i18nObjs } from "../../i18n/index";
3333
import { DatasourceInfo, HttpConfig } from "api/datasourceApi";
3434
import { enObj } from "i18n/locales";
3535
import { QUICK_REST_API_ID } from "constants/datasourceConstants";
36+
import React from "react";
3637

3738
const tourSteps: Step[] = [
3839
{
@@ -203,7 +204,7 @@ function addQuery(editorState: EditorState, datasourceInfos: DatasourceInfo[]) {
203204
editorState.setSelectedBottomRes(queryName, BottomResTypeEnum.Query);
204205
}
205206

206-
export default function EditorTutorials() {
207+
function EditorTutorials() {
207208
const [run, setRun] = useState(false);
208209
const [stepIndex, setStepIndex] = useState(0);
209210
const editorState = useContext(EditorContext);
@@ -309,3 +310,5 @@ export default function EditorTutorials() {
309310
/>
310311
);
311312
}
313+
314+
export default React.memo(EditorTutorials);

0 commit comments

Comments
 (0)
Please sign in to comment.