Skip to content

Commit

Permalink
Merge pull request #1159 from lowcoder-org/minimize-rerendering-2
Browse files Browse the repository at this point in the history
Added memoization to minimize re-rendering
  • Loading branch information
FalkWolsky authored Sep 12, 2024
2 parents fe9a35c + 4bafc34 commit 33a4848
Show file tree
Hide file tree
Showing 14 changed files with 262 additions and 200 deletions.
10 changes: 5 additions & 5 deletions client/packages/lowcoder/src/comps/comps/gridItemComp.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ const TmpComp = withTypeAndChildren<
childrenMap
);

function CachedView(props: { comp: Comp; name: string }) {
const CachedView = React.memo((props: { comp: Comp; name: string }) => {
return React.useMemo(
() => (
<Profiler id={props.name} onRender={profilerCallback}>
Expand All @@ -73,13 +73,13 @@ function CachedView(props: { comp: Comp; name: string }) {
),
[props.comp, props.name]
);
}
})

function CachedPropertyView(props: {
const CachedPropertyView = React.memo((props: {
comp: Comp;
name: string;
withParamsContext: WithParamsContext;
}) {
}) => {
const prevHints = useContext(CompExposingContext);
const { withParamsContext } = props;
const hints = useMemo(
Expand Down Expand Up @@ -109,7 +109,7 @@ function CachedPropertyView(props: {
</>
);
}, [props.comp, props.name, hints, searchText, setSearchText]);
}
});

export class GridItemComp extends TmpComp {
private readonly withParamsContext: WithParamsContext = { params: {} };
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import styled from "styled-components";
import { RemoteCompInfo } from "types/remoteComp";
import { withErrorBoundary } from "comps/generators/withErrorBoundary";
import { ThemeContext } from "@lowcoder-ee/comps/utils/themeContext";
import React from "react";

const ViewError = styled.div`
display: flex;
Expand Down Expand Up @@ -50,7 +51,7 @@ interface LazyCompViewProps {
errorElement?: (error: any) => React.ReactNode;
}

function LazyCompView(props: React.PropsWithChildren<LazyCompViewProps>) {
const LazyCompView = React.memo((props: React.PropsWithChildren<LazyCompViewProps>) => {
const { loadComp, loadingElement, errorElement } = props;
const [error, setError] = useState<any>("");
const currentTheme = useContext(ThemeContext)?.theme;
Expand Down Expand Up @@ -83,7 +84,7 @@ function LazyCompView(props: React.PropsWithChildren<LazyCompViewProps>) {
return (
<WhiteLoading />
);
}
});

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

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { loaders } from "./loaders";
import { withErrorBoundary } from "comps/generators/withErrorBoundary";
import { EditorContext } from "@lowcoder-ee/comps/editorState";
import { CompContext } from "@lowcoder-ee/comps/utils/compContext";
import React from "react";

const ViewError = styled.div`
display: flex;
Expand Down Expand Up @@ -53,7 +54,7 @@ interface RemoteCompViewProps {
errorElement?: (error: any) => React.ReactNode;
}

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

return (
<ViewLoadingWrapper>
<WhiteLoading />
</ViewLoadingWrapper>
<WhiteLoading />
);
}
});

export function remoteComp<T extends RemoteCompInfo = RemoteCompInfo>(
remoteInfo?: T,
Expand Down
161 changes: 86 additions & 75 deletions client/packages/lowcoder/src/comps/comps/textComp.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ import { PaddingControl } from "../controls/paddingControl";
import React, { useContext, useEffect } from "react";
import { EditorContext } from "comps/editorState";
import { clickEvent, eventHandlerControl } from "../controls/eventHandlerControl";
import { NewChildren } from "../generators/uiCompBuilder";
import { RecordConstructorToComp } from "lowcoder-core";
import { ToViewReturn } from "../generators/multi";

const EventOptions = [clickEvent] as const;

Expand Down Expand Up @@ -130,87 +133,95 @@ const VerticalAlignmentOptions = [
{ label: <AlignVerticalCenter />, value: "center" },
{ label: <AlignBottom />, value: "flex-end" },
] as const;
const childrenMap = {
text: stringExposingStateControl(
"text",
trans("textShow.text", { name: "{{currentUser.name}}" })
),
onEvent: eventHandlerControl(EventOptions),
autoHeight: AutoHeightControl,
type: dropdownControl(typeOptions, "markdown"),
horizontalAlignment: alignWithJustifyControl(),
verticalAlignment: dropdownControl(VerticalAlignmentOptions, "center"),
style: styleControl(TextStyle, 'style'),
animationStyle: styleControl(AnimationStyle, 'animationStyle'),
margin: MarginControl,
padding: PaddingControl,
};

let TextTmpComp = (function () {
const childrenMap = {
text: stringExposingStateControl(
"text",
trans("textShow.text", { name: "{{currentUser.name}}" })
),
onEvent: eventHandlerControl(EventOptions),
autoHeight: AutoHeightControl,
type: dropdownControl(typeOptions, "markdown"),
horizontalAlignment: alignWithJustifyControl(),
verticalAlignment: dropdownControl(VerticalAlignmentOptions, "center"),
style: styleControl(TextStyle, 'style'),
animationStyle: styleControl(AnimationStyle, 'animationStyle'),
margin: MarginControl,
padding: PaddingControl,
};
return new UICompBuilder(childrenMap, (props, dispatch) => {
const value = props.text.value;

return (
<TextContainer
$animationStyle={props.animationStyle}
$type={props.type}
$styleConfig={props.style}
style={{
justifyContent: props.horizontalAlignment,
alignItems: props.autoHeight ? "center" : props.verticalAlignment,
textAlign: props.horizontalAlignment,
rotate: props.style.rotation
}}
onClick={() => props.onEvent("click")}
>
{props.type === "markdown" ? <TacoMarkDown>{value}</TacoMarkDown> : value}
</TextContainer>
);
})
.setPropertyViewFn((children) => {
return (
type ChildrenType = NewChildren<RecordConstructorToComp<typeof childrenMap>>;

const TextPropertyView = React.memo((props: {
children: ChildrenType
}) => {
return (
<>
<Section name={sectionNames.basic}>
{props.children.type.propertyView({
label: trans("value"),
tooltip: trans("textShow.valueTooltip"),
radioButton: true,
})}
{props.children.text.propertyView({})}
</Section>

{["logic", "both"].includes(useContext(EditorContext).editorModeStatus) && (
<Section name={sectionNames.interaction}>
{hiddenPropertyView(props.children)}
{props.children.onEvent.getPropertyView()}
</Section>
)}

{["layout", "both"].includes(useContext(EditorContext).editorModeStatus) && (
<>
<Section name={sectionNames.basic}>
{children.type.propertyView({
label: trans("value"),
tooltip: trans("textShow.valueTooltip"),
<Section name={sectionNames.layout}>
{props.children.autoHeight.getPropertyView()}
{!props.children.autoHeight.getView() &&
props.children.verticalAlignment.propertyView({
label: trans("textShow.verticalAlignment"),
radioButton: true,
})}
{props.children.horizontalAlignment.propertyView({
label: trans("textShow.horizontalAlignment"),
radioButton: true,
})}
{children.text.propertyView({})}
</Section>

{["logic", "both"].includes(useContext(EditorContext).editorModeStatus) && (
<Section name={sectionNames.interaction}>
{hiddenPropertyView(children)}
{children.onEvent.getPropertyView()}
</Section>
)}

{["layout", "both"].includes(useContext(EditorContext).editorModeStatus) && (
<>
<Section name={sectionNames.layout}>
{children.autoHeight.getPropertyView()}
{!children.autoHeight.getView() &&
children.verticalAlignment.propertyView({
label: trans("textShow.verticalAlignment"),
radioButton: true,
})}
{children.horizontalAlignment.propertyView({
label: trans("textShow.horizontalAlignment"),
radioButton: true,
})}
</Section>
<Section name={sectionNames.style}>
{children.style.getPropertyView()}
</Section>
<Section name={sectionNames.animationStyle} hasTooltip={true}>
{children.animationStyle.getPropertyView()}
</Section>
</>
)}
<Section name={sectionNames.style}>
{props.children.style.getPropertyView()}
</Section>
<Section name={sectionNames.animationStyle} hasTooltip={true}>
{props.children.animationStyle.getPropertyView()}
</Section>
</>
);
})
)}
</>
);
})

const TextView = React.memo((props: ToViewReturn<ChildrenType>) => {
const value = props.text.value;

return (
<TextContainer
$animationStyle={props.animationStyle}
$type={props.type}
$styleConfig={props.style}
style={{
justifyContent: props.horizontalAlignment,
alignItems: props.autoHeight ? "center" : props.verticalAlignment,
textAlign: props.horizontalAlignment,
rotate: props.style.rotation
}}
onClick={() => props.onEvent("click")}
>
{props.type === "markdown" ? <TacoMarkDown>{value}</TacoMarkDown> : value}
</TextContainer>
);
}, (prev, next) => JSON.stringify(prev) === JSON.stringify(next));

let TextTmpComp = (function () {
return new UICompBuilder(childrenMap, (props) => <TextView {...props} />)
.setPropertyViewFn((children) => <TextPropertyView children={children} />)
.build();
})();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -359,6 +359,7 @@ export function optionsControl<T extends OptionsControlType>(
uniqField?: keyof ConstructorToView<T>;
// manual mode list title
title?: string;
autoIncField?: keyof PickNumberFields<ConstructorToView<T>>;
}
) {
type OptionViewType = ConstructorToView<T>;
Expand All @@ -369,6 +370,7 @@ export function optionsControl<T extends OptionsControlType>(
manual: manualOptionsControl(VariantComp, {
initOptions: config.initOptions,
uniqField: config.uniqField,
autoIncField: config.autoIncField,
}),
mapData: mapOptionsControl(VariantComp, config.uniqField),
},
Expand Down
17 changes: 10 additions & 7 deletions client/packages/lowcoder/src/comps/controls/slotControl.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ import { createContext, useContext } from "react";
import styled from "styled-components";
import { NameGenerator } from "comps/utils";
import { JSONValue } from "util/jsonTypes";
import React from "react";
import { isEqual } from "lodash";

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

const ContainerView = (props: ContainerBaseProps) => {
const ContainerView = React.memo((props: ContainerBaseProps) => {
return <InnerGrid {...props} emptyRows={15} autoHeight />;
};
});

function ModalConfigView(props: {
const ModalConfigView = React.memo((props: {
visible: boolean;
containerProps: ConstructorToView<typeof SimpleContainerComp>;
onCancel: () => void;
}) {
}) => {
const { visible, containerProps, onCancel } = props;
const background = useContext(BackgroundColorContext);
const { modalWidth = 520 } = useContext(SlotConfigContext);
if (!visible) {
return null;
}
return (
(<ModalWrapper>
<ModalWrapper>
<Modal
width={modalWidth}
open={visible}
Expand All @@ -67,6 +69,7 @@ function ModalConfigView(props: {
footer={null}
styles={{ body: {padding: "0"} }}
zIndex={Layers.modal}
maskClosable={false}
modalRender={(node) => (
<ModalStyled $background={background} onClick={() => {}}>
{node}
Expand All @@ -81,9 +84,9 @@ function ModalConfigView(props: {
items={gridItemCompToGridItems(containerProps.items)}
/>
</Modal>
</ModalWrapper>)
</ModalWrapper>
);
}
}, (prevProps, nextProps) => isEqual(prevProps, nextProps));

const childrenMap = {
container: SimpleContainerComp,
Expand Down
Loading

0 comments on commit 33a4848

Please sign in to comment.