Skip to content

Commit 9fe41dd

Browse files
committed
refactor: fix mobx action/computed hygiene and reaction leak
- Add FileStore.reset() action; was mutating observables outside action - Move sort to sortedFiles computed; recalculates only when files change - Dispose reaction on unmount to prevent leak
1 parent 7d054a3 commit 9fe41dd

4 files changed

Lines changed: 38 additions & 21 deletions

File tree

packages/pluggableWidgets/file-uploader-web/src/components/FileUploaderRoot.tsx

Lines changed: 9 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -34,21 +34,15 @@ export const FileUploaderRoot = observer((props: FileUploaderContainerProps): Re
3434
)}
3535

3636
<div className={"files-list"}>
37-
{[...(rootStore.files ?? [])]
38-
.sort((a, b) => {
39-
const isErrorA = a.fileStatus === "validationError" ? 1 : 0;
40-
const isErrorB = b.fileStatus === "validationError" ? 1 : 0;
41-
return isErrorA - isErrorB;
42-
})
43-
.map(fileStore => {
44-
return (
45-
<FileEntryContainer
46-
store={fileStore}
47-
key={fileStore.key}
48-
actions={props.enableCustomButtons ? props.customButtons : undefined}
49-
/>
50-
);
51-
})}
37+
{rootStore.sortedFiles.map(fileStore => {
38+
return (
39+
<FileEntryContainer
40+
store={fileStore}
41+
key={fileStore.key}
42+
actions={props.enableCustomButtons ? props.customButtons : undefined}
43+
/>
44+
);
45+
})}
5246
</div>
5347
</div>
5448
);

packages/pluggableWidgets/file-uploader-web/src/stores/FileStore.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,8 @@ export class FileStore {
6363
upload: action,
6464
fetchMxObject: action,
6565
markMissing: action,
66-
markError: action
66+
markError: action,
67+
reset: action
6768
});
6869
}
6970

@@ -80,6 +81,12 @@ export class FileStore {
8081
this.errorType = errorType;
8182
}
8283

84+
reset(): void {
85+
this.errorType = undefined;
86+
this.errorDescription = undefined;
87+
this.fileStatus = "new";
88+
}
89+
8390
canExecute(listAction: ListActionValue): boolean {
8491
if (!this._objectItem) {
8592
return false;

packages/pluggableWidgets/file-uploader-web/src/stores/FileUploaderStore.ts

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ export class FileUploaderStore {
2828
_maxFileSize = 0;
2929
_maxFilesPerUpload: DynamicValue<Big> | undefined;
3030
_maxFilesPerBatch: DynamicValue<Big> | undefined;
31+
_disposeRetryReaction: (() => void) | undefined;
3132

3233
errorMessage?: string = undefined;
3334

@@ -89,12 +90,13 @@ export class FileUploaderStore {
8990
_maxFilesPerUpload: observable,
9091
_maxFilesPerBatch: observable,
9192
isFileUploadLimitReached: computed,
92-
warningMessage: computed
93+
warningMessage: computed,
94+
sortedFiles: computed
9395
});
9496

9597
this.updateProps(props);
9698

97-
reaction(
99+
this._disposeRetryReaction = reaction(
98100
() =>
99101
this.files.filter(
100102
f =>
@@ -167,6 +169,14 @@ export class FileUploaderStore {
167169
return activeFiles.length >= this.maxFilesPerUpload;
168170
}
169171

172+
get sortedFiles(): FileStore[] {
173+
return [...this.files].sort((a, b) => {
174+
const isErrorA = a.fileStatus === "validationError" ? 1 : 0;
175+
const isErrorB = b.fileStatus === "validationError" ? 1 : 0;
176+
return isErrorA - isErrorB;
177+
});
178+
}
179+
170180
get warningMessage(): string | undefined {
171181
if (this.isFileUploadLimitReached) {
172182
return this.translations.get("uploadLimitReachedMessage", this.maxFilesPerUpload.toString());
@@ -205,15 +215,17 @@ export class FileUploaderStore {
205215

206216
for (let i = 0; i < Math.min(slots, waiting.length); i++) {
207217
const file = waiting[i];
208-
file.errorType = undefined;
209-
file.errorDescription = undefined;
210-
file.fileStatus = "new";
218+
file.reset();
211219
if (file.validate()) {
212220
file.upload();
213221
}
214222
}
215223
}
216224

225+
dispose(): void {
226+
this._disposeRetryReaction?.();
227+
}
228+
217229
processDrop(acceptedFiles: File[], fileRejections: FileRejection[]): void {
218230
if (!this.objectCreationHelper.canCreateFiles) {
219231
console.error(

packages/pluggableWidgets/file-uploader-web/src/utils/useRootStore.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,5 +13,9 @@ export function useRootStore(props: FileUploaderContainerProps): FileUploaderSto
1313
rootStore.updateProps(props);
1414
}, [rootStore, props]);
1515

16+
useEffect(() => {
17+
return () => rootStore.dispose();
18+
}, [rootStore]);
19+
1620
return rootStore;
1721
}

0 commit comments

Comments
 (0)