Skip to content

Commit dde6838

Browse files
table optimisations
1 parent b637bf6 commit dde6838

File tree

9 files changed

+153
-110
lines changed

9 files changed

+153
-110
lines changed

client/packages/lowcoder/src/app.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ const LazyDebugNewComp = React.lazy(() => import("./debugNew"));
7676
const Wrapper = (props: { children: React.ReactNode, language: string }) => (
7777
<ConfigProvider
7878
theme={{ hashed: false }}
79+
wave={{ disabled: true }}
7980
locale={getAntdLocale(props.language)}
8081
>
8182
<App>

client/packages/lowcoder/src/components/table/EditableCell.tsx

Lines changed: 45 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ export interface CellProps {
4646
cellTooltip?: string;
4747
editMode?: string;
4848
onTableEvent?: (eventName: any) => void;
49+
cellIndex?: string;
4950
}
5051

5152
export type CellViewReturn = (props: CellProps) => ReactNode;
@@ -65,7 +66,7 @@ const BorderDiv = styled.div`
6566
left: 0;
6667
`;
6768

68-
const CellWrapper = ({
69+
const CellWrapper = React.memo(({
6970
children,
7071
tooltipTitle,
7172
}: {
@@ -82,7 +83,7 @@ const CellWrapper = ({
8283
return (
8384
<>{children}</>
8485
)
85-
};
86+
});
8687

8788
interface EditableCellProps<T> extends CellProps {
8889
normalView: ReactNode;
@@ -108,6 +109,7 @@ function EditableCellComp<T extends JSONValue>(props: EditableCellProps<T>) {
108109
tableSize,
109110
textOverflow,
110111
cellTooltip,
112+
cellIndex,
111113
...otherProps
112114
} = props;
113115

@@ -118,15 +120,23 @@ function EditableCellComp<T extends JSONValue>(props: EditableCellProps<T>) {
118120
const [tmpValue, setTmpValue] = useState<T | null>(value);
119121
const singleClickEdit = editMode === 'single';
120122

121-
// Use refs to track previous values for comparison
123+
// Use refs to track component mount state and previous values
124+
const mountedRef = useRef(true);
122125
const prevValueRef = useRef(value);
123126

127+
// Cleanup on unmount
124128
useEffect(() => {
125-
console.log("rendered EditableCellComp");
126-
}, []);
129+
return () => {
130+
mountedRef.current = false;
131+
setTmpValue(null);
132+
setIsEditing(false);
133+
};
134+
}, [setIsEditing]);
127135

128136
// Update tmpValue when value changes
129137
useEffect(() => {
138+
if (!mountedRef.current) return;
139+
130140
if (!_.isEqual(value, prevValueRef.current)) {
131141
setTmpValue(value);
132142
prevValueRef.current = value;
@@ -135,12 +145,15 @@ function EditableCellComp<T extends JSONValue>(props: EditableCellProps<T>) {
135145

136146
const onChange = useCallback(
137147
(value: T) => {
148+
if (!mountedRef.current) return;
138149
setTmpValue(value);
139150
},
140151
[]
141152
);
142153

143154
const onChangeEnd = useCallback(() => {
155+
if (!mountedRef.current) return;
156+
144157
setIsEditing(false);
145158
const newValue = _.isNil(tmpValue) || _.isEqual(tmpValue, baseValue) ? null : tmpValue;
146159
dispatch(
@@ -153,32 +166,28 @@ function EditableCellComp<T extends JSONValue>(props: EditableCellProps<T>) {
153166
if(!_.isEqual(tmpValue, value)) {
154167
onTableEvent?.('columnEdited');
155168
}
156-
}, [dispatch, tmpValue, baseValue, value, onTableEvent]);
169+
}, [dispatch, tmpValue, baseValue, value, onTableEvent, setIsEditing]);
157170

158171
const editView = useMemo(
159172
() => editViewFn?.({ value, onChange, onChangeEnd, otherProps }) ?? <></>,
160173
[editViewFn, value, onChange, onChangeEnd, otherProps]
161174
);
162175

163176
const enterEditFn = useCallback(() => {
164-
if (editable) setIsEditing(true);
177+
if (!mountedRef.current || !editable) return;
178+
setIsEditing(true);
165179
}, [editable, setIsEditing]);
166180

167-
// Cleanup function
168-
useEffect(() => {
169-
return () => {
170-
// Reset state on unmount
171-
setTmpValue(null);
172-
setIsEditing(false);
173-
};
174-
}, [setIsEditing]);
175-
181+
// Memoize context values to prevent unnecessary re-renders
182+
const tagsContextValue = useMemo(() => candidateTags ?? [], [candidateTags]);
183+
const statusContextValue = useMemo(() => candidateStatus ?? [], [candidateStatus]);
184+
176185
if (isEditing) {
177186
return (
178187
<>
179188
<BorderDiv className="editing-border" />
180-
<TagsContext.Provider value={candidateTags ?? []}>
181-
<StatusContext.Provider value={candidateStatus ?? []}>
189+
<TagsContext.Provider value={tagsContextValue}>
190+
<StatusContext.Provider value={statusContextValue}>
182191
<div className="editing-wrapper">
183192
{editView}
184193
</div>
@@ -189,30 +198,30 @@ function EditableCellComp<T extends JSONValue>(props: EditableCellProps<T>) {
189198
}
190199

191200
return (
192-
<ColumnTypeView
193-
textOverflow={props.textOverflow}
194-
>
195-
{status === "toSave" && !isEditing && <EditableChip key={`editable-chip`}/>}
201+
<ColumnTypeView
202+
textOverflow={props.textOverflow}
203+
>
204+
{status === "toSave" && !isEditing && <EditableChip key={`editable-chip-${cellIndex}`}/>}
205+
<CellWrapper tooltipTitle={props.cellTooltip}>
206+
<div
207+
key={`normal-view-${cellIndex}`}
208+
tabIndex={editable ? 0 : -1 }
209+
onFocus={enterEditFn}
210+
>
211+
{normalView}
212+
</div>
213+
</CellWrapper>
214+
{/* overlay on normal view to handle double click for editing */}
215+
{editable && (
196216
<CellWrapper tooltipTitle={props.cellTooltip}>
197-
<div
198-
key={`normal-view`}
199-
tabIndex={editable ? 0 : -1 }
200-
onFocus={enterEditFn}
201-
>
202-
{normalView}
203-
</div>
204-
</CellWrapper>
205-
{/* overlay on normal view to handle double click for editing */}
206-
{editable && (
207-
<CellWrapper tooltipTitle={props.cellTooltip}>
208217
<EditableOverlay
209-
key="editable-view"
218+
key={`editable-view-${cellIndex}`}
210219
onDoubleClick={!singleClickEdit ? enterEditFn : undefined}
211220
onClick={singleClickEdit ? enterEditFn : undefined}
212221
/>
213222
</CellWrapper>
214-
)}
215-
</ColumnTypeView>
223+
)}
224+
</ColumnTypeView>
216225
);
217226
}
218227

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy