-
-
Notifications
You must be signed in to change notification settings - Fork 4.7k
Description
Describe the problem
Not sure if it's a bug, but I encountered a really strange behaviour. I am trying to make a reloadable state to contain arrays. I ended up with
export class ReloadableArray<T> extends Array<T> {
private loading = $state(false);
private updateFn: () => T[] | Promise<T[]> = () => [];
constructor(initialValue: T[], updateFn: () => T[] | Promise<T[]>) {
super();
if (Array.isArray(initialValue)) {
initialValue.forEach((item) => this.push(item));
}
if (typeof updateFn === "function") {
this.updateFn = updateFn;
setTimeout(() => {
void this.reload();
}, 0);
}
}
async reload(): Promise<void> {
this.loading = true;
try {
const updatedValues = await this.updateFn();
this.length = 0;
updatedValues.forEach((value) => this.push(value));
} catch (error) {
console.error("Error reloading data:", error);
} finally {
this.loading = false;
}
}
get isLoading(): boolean {
return this.loading;
}
}
then it is used in this way
let items = $derived(customSort(new ReloadableArray<MyType>([emptyItem], () => { [call to API] })));
and the items are used in a component that draws a combobox. The component uses Svelte 4 and uses {#each}.
The weird behavior is this: items are loaded and the combobox is updated, but customSort() is called only the first time on the empty element. Note that customSort() return its argument if the length is <=1. So, i think the component maintains a reference to the original array, and this is reactive, but $derived() is working only on initialization. I would expect it to work always, or not to work at all.
Describe the proposed solution
I'd like to have reactivity on extended arrays.
Importance
nice to have