diff --git a/js/src/common/components/SharedFileList.tsx b/js/src/common/components/SharedFileList.tsx index a6e38a9a..a10462e4 100644 --- a/js/src/common/components/SharedFileList.tsx +++ b/js/src/common/components/SharedFileList.tsx @@ -4,6 +4,9 @@ import AbstractFileList from './AbstractFIleList'; export default class SharedFileList extends AbstractFileList { public loadFileList(): void { + // Mirror UserFileList's setUser guard: skip if already loaded or a fetch is in flight, + // otherwise rapid tab toggling fires concurrent requests and parseResults concats duplicates. + if (this.fileState.files.length > 0 || this.fileState.isLoading()) return; this.fileState.loadResults(); } diff --git a/js/src/common/states/FileListState.ts b/js/src/common/states/FileListState.ts index cb1e36f6..a5b60781 100644 --- a/js/src/common/states/FileListState.ts +++ b/js/src/common/states/FileListState.ts @@ -66,9 +66,16 @@ export default class FileListState { } as ApiQueryParamsPlural; } - const results = await app.store.find(route, params); - - return this.parseResults(results); + try { + const results = await app.store.find(route, params); + return this.parseResults(results); + } catch (error) { + // Ensure loading is reset on failure so consumers (e.g. SharedFileList's loadFileList guard) + // can detect that the previous attempt finished and a retry is allowed. + this.loading = false; + m.redraw(); + throw error; + } } /**