Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 33a4848

Browse files
Merge pull request #1159 from lowcoder-org/minimize-rerendering-2
Added memoization to minimize re-rendering
2 parents fe9a35c + 4bafc34 commit 33a4848

File tree

14 files changed

+262
-200
lines changed

14 files changed

+262
-200
lines changed

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

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ const TmpComp = withTypeAndChildren<
6262
childrenMap
6363
);
6464

65-
function CachedView(props: { comp: Comp; name: string }) {
65+
const CachedView=React.memo((props: { comp: Comp; name: string })=> {
6666
return React.useMemo(
6767
() => (
6868
<Profiler id={props.name} onRender={profilerCallback}>
@@ -73,13 +73,13 @@ function CachedView(props: { comp: Comp; name: string }) {
7373
),
7474
[props.comp, props.name]
7575
);
76-
}
76+
})
7777

78-
function CachedPropertyView(props: {
78+
const CachedPropertyView=React.memo((props: {
7979
comp: Comp;
8080
name: string;
8181
withParamsContext: WithParamsContext;
82-
}) {
82+
}) =>{
8383
const prevHints = useContext(CompExposingContext);
8484
const { withParamsContext } = props;
8585
const hints = useMemo(
@@ -109,7 +109,7 @@ function CachedPropertyView(props: {
109109
</>
110110
);
111111
}, [props.comp, props.name, hints, searchText, setSearchText]);
112-
}
112+
});
113113

114114
export class GridItemComp extends TmpComp {
115115
private readonly withParamsContext: WithParamsContext = { params: {} };

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import styled from "styled-components";
1111
import { RemoteCompInfo } from "types/remoteComp";
1212
import { withErrorBoundary } from "comps/generators/withErrorBoundary";
1313
import { ThemeContext } from "@lowcoder-ee/comps/utils/themeContext";
14+
import React from "react";
1415

1516
const ViewError = styled.div`
1617
display: flex;
@@ -50,7 +51,7 @@ interface LazyCompViewProps {
5051
errorElement?: (error: any) => React.ReactNode;
5152
}
5253

53-
function LazyCompView(props: React.PropsWithChildren<LazyCompViewProps>) {
54+
const LazyCompView=React.memo((props: React.PropsWithChildren<LazyCompViewProps>)=> {
5455
const { loadComp, loadingElement, errorElement } = props;
5556
const [error, setError] = useState<any>("");
5657
const currentTheme = useContext(ThemeContext)?.theme;
@@ -83,7 +84,7 @@ function LazyCompView(props: React.PropsWithChildren<LazyCompViewProps>) {
8384
return (
8485
<WhiteLoading />
8586
);
86-
}
87+
});
8788

8889
export type LazyloadCompLoader<T = RemoteCompInfo> = () => Promise<CompConstructor | null>;
8990

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

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import { loaders } from "./loaders";
1313
import { withErrorBoundary } from "comps/generators/withErrorBoundary";
1414
import { EditorContext } from "@lowcoder-ee/comps/editorState";
1515
import { CompContext } from "@lowcoder-ee/comps/utils/compContext";
16+
import React from "react";
1617

1718
const ViewError = styled.div`
1819
display: flex;
@@ -53,7 +54,7 @@ interface RemoteCompViewProps {
5354
errorElement?: (error: any) => React.ReactNode;
5455
}
5556

56-
function RemoteCompView(props: React.PropsWithChildren<RemoteCompViewProps>) {
57+
const RemoteCompView=React.memo((props: React.PropsWithChildren<RemoteCompViewProps>)=> {
5758
const { loadComp, loadingElement, errorElement, isLowcoderComp } = props;
5859
const [error, setError] = useState<any>("");
5960
const editorState = useContext(EditorContext);
@@ -93,11 +94,9 @@ function RemoteCompView(props: React.PropsWithChildren<RemoteCompViewProps>) {
9394
}
9495

9596
return (
96-
<ViewLoadingWrapper>
97-
<WhiteLoading />
98-
</ViewLoadingWrapper>
97+
<WhiteLoading />
9998
);
100-
}
99+
});
101100

102101
export function remoteComp<T extends RemoteCompInfo = RemoteCompInfo>(
103102
remoteInfo?: T,

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

Lines changed: 86 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@ import { PaddingControl } from "../controls/paddingControl";
2121
import React, { useContext, useEffect } from "react";
2222
import { EditorContext } from "comps/editorState";
2323
import { clickEvent, eventHandlerControl } from "../controls/eventHandlerControl";
24+
import { NewChildren } from "../generators/uiCompBuilder";
25+
import { RecordConstructorToComp } from "lowcoder-core";
26+
import { ToViewReturn } from "../generators/multi";
2427

2528
const EventOptions = [clickEvent] as const;
2629

@@ -130,87 +133,95 @@ const VerticalAlignmentOptions = [
130133
{ label: <AlignVerticalCenter />, value: "center" },
131134
{ label: <AlignBottom />, value: "flex-end" },
132135
] as const;
136+
const childrenMap = {
137+
text: stringExposingStateControl(
138+
"text",
139+
trans("textShow.text", { name: "{{currentUser.name}}" })
140+
),
141+
onEvent: eventHandlerControl(EventOptions),
142+
autoHeight: AutoHeightControl,
143+
type: dropdownControl(typeOptions, "markdown"),
144+
horizontalAlignment: alignWithJustifyControl(),
145+
verticalAlignment: dropdownControl(VerticalAlignmentOptions, "center"),
146+
style: styleControl(TextStyle, 'style'),
147+
animationStyle: styleControl(AnimationStyle, 'animationStyle'),
148+
margin: MarginControl,
149+
padding: PaddingControl,
150+
};
133151

134-
let TextTmpComp = (function () {
135-
const childrenMap = {
136-
text: stringExposingStateControl(
137-
"text",
138-
trans("textShow.text", { name: "{{currentUser.name}}" })
139-
),
140-
onEvent: eventHandlerControl(EventOptions),
141-
autoHeight: AutoHeightControl,
142-
type: dropdownControl(typeOptions, "markdown"),
143-
horizontalAlignment: alignWithJustifyControl(),
144-
verticalAlignment: dropdownControl(VerticalAlignmentOptions, "center"),
145-
style: styleControl(TextStyle, 'style'),
146-
animationStyle: styleControl(AnimationStyle, 'animationStyle'),
147-
margin: MarginControl,
148-
padding: PaddingControl,
149-
};
150-
return new UICompBuilder(childrenMap, (props, dispatch) => {
151-
const value = props.text.value;
152-
153-
return (
154-
<TextContainer
155-
$animationStyle={props.animationStyle}
156-
$type={props.type}
157-
$styleConfig={props.style}
158-
style={{
159-
justifyContent: props.horizontalAlignment,
160-
alignItems: props.autoHeight ? "center" : props.verticalAlignment,
161-
textAlign: props.horizontalAlignment,
162-
rotate: props.style.rotation
163-
}}
164-
onClick={() => props.onEvent("click")}
165-
>
166-
{props.type === "markdown" ? <TacoMarkDown>{value}</TacoMarkDown> : value}
167-
</TextContainer>
168-
);
169-
})
170-
.setPropertyViewFn((children) => {
171-
return (
152+
type ChildrenType = NewChildren<RecordConstructorToComp<typeof childrenMap>>;
153+
154+
const TextPropertyView = React.memo((props: {
155+
children: ChildrenType
156+
}) => {
157+
return (
158+
<>
159+
<Section name={sectionNames.basic}>
160+
{props.children.type.propertyView({
161+
label: trans("value"),
162+
tooltip: trans("textShow.valueTooltip"),
163+
radioButton: true,
164+
})}
165+
{props.children.text.propertyView({})}
166+
</Section>
167+
168+
{["logic", "both"].includes(useContext(EditorContext).editorModeStatus) && (
169+
<Section name={sectionNames.interaction}>
170+
{hiddenPropertyView(props.children)}
171+
{props.children.onEvent.getPropertyView()}
172+
</Section>
173+
)}
174+
175+
{["layout", "both"].includes(useContext(EditorContext).editorModeStatus) && (
172176
<>
173-
<Section name={sectionNames.basic}>
174-
{children.type.propertyView({
175-
label: trans("value"),
176-
tooltip: trans("textShow.valueTooltip"),
177+
<Section name={sectionNames.layout}>
178+
{props.children.autoHeight.getPropertyView()}
179+
{!props.children.autoHeight.getView() &&
180+
props.children.verticalAlignment.propertyView({
181+
label: trans("textShow.verticalAlignment"),
182+
radioButton: true,
183+
})}
184+
{props.children.horizontalAlignment.propertyView({
185+
label: trans("textShow.horizontalAlignment"),
177186
radioButton: true,
178187
})}
179-
{children.text.propertyView({})}
180188
</Section>
181-
182-
{["logic", "both"].includes(useContext(EditorContext).editorModeStatus) && (
183-
<Section name={sectionNames.interaction}>
184-
{hiddenPropertyView(children)}
185-
{children.onEvent.getPropertyView()}
186-
</Section>
187-
)}
188-
189-
{["layout", "both"].includes(useContext(EditorContext).editorModeStatus) && (
190-
<>
191-
<Section name={sectionNames.layout}>
192-
{children.autoHeight.getPropertyView()}
193-
{!children.autoHeight.getView() &&
194-
children.verticalAlignment.propertyView({
195-
label: trans("textShow.verticalAlignment"),
196-
radioButton: true,
197-
})}
198-
{children.horizontalAlignment.propertyView({
199-
label: trans("textShow.horizontalAlignment"),
200-
radioButton: true,
201-
})}
202-
</Section>
203-
<Section name={sectionNames.style}>
204-
{children.style.getPropertyView()}
205-
</Section>
206-
<Section name={sectionNames.animationStyle} hasTooltip={true}>
207-
{children.animationStyle.getPropertyView()}
208-
</Section>
209-
</>
210-
)}
189+
<Section name={sectionNames.style}>
190+
{props.children.style.getPropertyView()}
191+
</Section>
192+
<Section name={sectionNames.animationStyle} hasTooltip={true}>
193+
{props.children.animationStyle.getPropertyView()}
194+
</Section>
211195
</>
212-
);
213-
})
196+
)}
197+
</>
198+
);
199+
})
200+
201+
const TextView = React.memo((props: ToViewReturn<ChildrenType>) => {
202+
const value = props.text.value;
203+
204+
return (
205+
<TextContainer
206+
$animationStyle={props.animationStyle}
207+
$type={props.type}
208+
$styleConfig={props.style}
209+
style={{
210+
justifyContent: props.horizontalAlignment,
211+
alignItems: props.autoHeight ? "center" : props.verticalAlignment,
212+
textAlign: props.horizontalAlignment,
213+
rotate: props.style.rotation
214+
}}
215+
onClick={() => props.onEvent("click")}
216+
>
217+
{props.type === "markdown" ? <TacoMarkDown>{value}</TacoMarkDown> : value}
218+
</TextContainer>
219+
);
220+
}, (prev, next) => JSON.stringify(prev) === JSON.stringify(next));
221+
222+
let TextTmpComp = (function () {
223+
return new UICompBuilder(childrenMap, (props) => <TextView {...props} />)
224+
.setPropertyViewFn((children) => <TextPropertyView children={children} />)
214225
.build();
215226
})();
216227

‎client/packages/lowcoder/src/comps/controls/optionsControl.tsx‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -359,6 +359,7 @@ export function optionsControl<T extends OptionsControlType>(
359359
uniqField?: keyof ConstructorToView<T>;
360360
// manual mode list title
361361
title?: string;
362+
autoIncField?: keyof PickNumberFields<ConstructorToView<T>>;
362363
}
363364
) {
364365
type OptionViewType = ConstructorToView<T>;
@@ -369,6 +370,7 @@ export function optionsControl<T extends OptionsControlType>(
369370
manual: manualOptionsControl(VariantComp, {
370371
initOptions: config.initOptions,
371372
uniqField: config.uniqField,
373+
autoIncField: config.autoIncField,
372374
}),
373375
mapData: mapOptionsControl(VariantComp, config.uniqField),
374376
},

‎client/packages/lowcoder/src/comps/controls/slotControl.tsx‎

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ import { createContext, useContext } from "react";
1616
import styled from "styled-components";
1717
import { NameGenerator } from "comps/utils";
1818
import { JSONValue } from "util/jsonTypes";
19+
import React from "react";
20+
import { isEqual } from "lodash";
1921

2022
const ModalStyled = styled.div<{ $background?: string }>`
2123
.ant-modal-content {
@@ -42,23 +44,23 @@ export const SlotConfigContext = createContext<{
4244
modalWidth: 520,
4345
});
4446

45-
const ContainerView = (props: ContainerBaseProps) => {
47+
const ContainerView = React.memo((props: ContainerBaseProps) => {
4648
return <InnerGrid {...props} emptyRows={15} autoHeight />;
47-
};
49+
});
4850

49-
function ModalConfigView(props: {
51+
const ModalConfigView=React.memo((props: {
5052
visible: boolean;
5153
containerProps: ConstructorToView<typeof SimpleContainerComp>;
5254
onCancel: () => void;
53-
}) {
55+
}) =>{
5456
const { visible, containerProps, onCancel } = props;
5557
const background = useContext(BackgroundColorContext);
5658
const { modalWidth = 520 } = useContext(SlotConfigContext);
5759
if (!visible) {
5860
return null;
5961
}
6062
return (
61-
(<ModalWrapper>
63+
<ModalWrapper>
6264
<Modal
6365
width={modalWidth}
6466
open={visible}
@@ -67,6 +69,7 @@ function ModalConfigView(props: {
6769
footer={null}
6870
styles={{ body: {padding: "0"} }}
6971
zIndex={Layers.modal}
72+
maskClosable={false}
7073
modalRender={(node) => (
7174
<ModalStyled $background={background} onClick={() => {}}>
7275
{node}
@@ -81,9 +84,9 @@ function ModalConfigView(props: {
8184
items={gridItemCompToGridItems(containerProps.items)}
8285
/>
8386
</Modal>
84-
</ModalWrapper>)
87+
</ModalWrapper>
8588
);
86-
}
89+
},(prevProps,nextProps)=>isEqual(prevProps,nextProps));
8790

8891
const childrenMap = {
8992
container: SimpleContainerComp,

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /