Keep array property of a class which is constantly reassigned reactive #284
-
I am currently working on a browser extension that hooks into a lot of functionality of a website in some pretty awkward ways. The extension works similarly to the Sponsorblock extension but for music platforms. A user can submit segments of the timeline to "skip" parts of songs they don't like. Every time I switch songs, I create a new "Song" class and (re)assign it to a I want the reactive array property of whichever song is assigned to the //Hypothetical example of what I need, sadly breaks my promise resolver from working.
let currentSong = van.state<Song>()
currentSong.val = reactive(new Song(player));
div(() => JSON.stringify(currentSong.val.skips)) //Should show the latest array state of the object assigned to `currentSong` But from everything I've tried, either the async loader of my class breaks, or reactivity of the class breaks. My "Song" class: export class Song {
id: string;
skips: Skip[] = [];
loadingPromise: Promise<Song>;
loadingResolver: (song: Song) => void;
loaded: boolean = false;
constructor(player: IAudioPlayer) {
const { promise, resolve } = Promise.withResolvers<Song>();
this.id = player._playerDependencies.name;
this.loadingPromise = promise;
this.loadingResolver = (song: Song) => resolve(song);
this.#load();
}
async #load() {
const storageData = await Song.#loadFromStorage(this.id);
if (storageData.success) {
this.skips.push(...storageData.data);
}
else {
const serverData = await Song.#loadFromServer(this.id);
if (serverData.success) {
this.skips.push(...serverData.data);
}
}
this.loadingResolver(this); // <-- This doesnt work with the example code from above.
}
static async #loadFromStorage(id: string) {
... //fetch data from indexedb
}
static async #loadFromServer(id: string): Promise<PromiseWithResolveData<Skip[]>> {
... //fetch data from the server
}
} What change can I make to my code to allow for reactivity? |
Beta Was this translation helpful? Give feedback.
Replies: 3 comments
-
I took a glance to your code. I'm not completely sure whether you need the One way to exclude fields from being reactive is to declare them as non-enumerable: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty#enumerable. |
Beta Was this translation helpful? Give feedback.
-
@SwatDoge This is exactly what you are trying to do (change the object passed to the reactive) I made a couple of working examples with your code |
Beta Was this translation helpful? Give feedback.
-
Sorry for the late reaction to the both of you, had a really rough weekend After playing around with sirens examples it turned out I had made a few other small unrelated mistakes in my code that caused things to not work properly. Even if I had written things properly at some point, it would've likely not worked. Thank you guys so much for your quick and detailed responses! I've got the code to work now :) |
Beta Was this translation helpful? Give feedback.
@SwatDoge
Pay attention to this caveat
https://vanjs.org/x#caveat-no-reuse-reactive
This is exactly what you are trying to do (change the object passed to the reactive)
I made a couple of working examples with your code
https://jsfiddle.net/Sirenko/t6fb91pv/
https://jsfiddle.net/Sirenko/d7uk1f53/
https://jsfiddle.net/Sirenko/cLx5qdzt/