Qwik resumability serialization change for non-serializable class instances
0 reputation · 24 Mar 2025, 18:41 UTC
0 reputation · 24 Mar 2025, 18:41 UTC
Qwik's resumability model serializes application state directly into the HTML so that traditional client-side hydration is unnecessary. In Qwik 1.x, useStore and useSignal handle primitive and plain-object data reliably, but the boundary becomes less predictable when a class instance containing methods or private fields crosses from server rendering into client-side de-serialization.
Because Qwik uses the $$ suffix to lazy-load functions, the framework must reconstruct the prototype chain when de-serializing state that originated outside the standard JSON payload. A class instance that relies on non-enumerable properties or custom prototypes may not survive that transition intact, creating a compatibility boundary between server-rendered HTML and client-side execution.
What is the documented pattern for wrapping non-serializable classes so they remain functional across the resumability boundary? How does Qwik 1.x handle de-serialization of methods and private properties that are not represented in the initial serialized state?
34775 reputation · 25 Mar 2025, 06:30 UTC
The documented pattern is to keep only plain, JSON‑serializable data in useStore or useSignal and rebuild the real class instance on the client after resumability.
useStore and useSignal state as JSON into the HTML q-data attribute.#) are not represented.The $$ suffix is used by Qwik to lazy‑load component functions, not to revive arbitrary class methods. Because JSON cannot capture functions or private state, the framework cannot restore them automatically; reconstruction must happen on the client after hydration.
{ id: number, name: string }).useStore or useSignal.useVisibleTask$ or useClientEffect$), instantiate the real class using a factory or constructor, passing the DTO as arguments.Use comments to ask for clarification. Post a solution as an answer.
34,775 reputation · 25 Mar 2025, 05:31 UTC
In addition to losing methods, Qwik’s JSON‑serialization also strips away any enumerable getters or setters defined on the class prototype, because only plain data properties are copied into the q-data attribute. Consequently, a store value that originated from a class instance arrives as a plain object whose Object.getPrototypeOf is Object.prototype, and any custom accessors are undefined.
Private fields (#field) are non‑enumerable and cannot be captured by JSON at all, so they are silently dropped; the only way to preserve that information is to expose it through a public getter or method that returns the value, and store that return value instead of the field itself.
Because the $$ suffix is reserved for lazy‑loading Qwik component code, it cannot be used to revive arbitrary class methods; the recommended pattern remains to keep only serializable data in useStore/useSignal and reconstruct the class instance in a client‑only initializer such as useVisibleTask$ or useClientEffect$.