#getting "QWIK WARN Serializing dirty watch. Looks like an internal error."
13 messages · Page 1 of 1 (latest)
try useVisibleTask$ instead of useTask$
I don't know why, but tracking a signal/store within useTask$ doesn't work, if the signal.value or store is changed in useResource$
Thanks Alex; I know that useVisibleTask works but I’m trying to understand what’s wrong with doing it in useTask… trying to get a deeper understanding.
This is working:
export default component$(() => {
const myResource = useResource$<string>(async () => {
return (await getScheduleData()).join('');
});
const store = useStore({ msg: '', translation: '' }, { deep: false });
const message = useSignal(myResource.value);
useTask$(async ({ track }) => {
const msg = await track(() => message.value);
store.msg = msg;
if (store.msg === 'HELLO WORLD') {
store.translation = 'BUENOS DIAS';
} else {
store.translation = 'waiting for translation...';
}
});
Based on my understanding, Watches (e.g., Signals and/or Stores) are marked as 'dirty' while they are being processed in a Task. In this case, useResource$ is a special type of useTask$. So, if you change store.msg within useResource$, you directly trigger useTask$, even while the store is still marked as 'dirty'. And useTask$ is not supposed to work with 'dirty' Watches. Only after useResource$ is resolved, the store would no longer be marked as 'dirty' and could be used in useTask$.
Wow, this makes sense @silk knot ; is this your guess or did you learn this from an official source?
Unfortunately no official source. I just had a look at the qwik source code.
@fervent sky @haughty vapor @frank nest Sorry to bother you guys, but when time allows, hoping someone could clarify whether this is a bug or incorrect usage of signals/store in useTask and useResource. Thank you!
I would say that this is currently a limitation of Qwik. There is an open issue on github about it (well not exactly the same, but very similar reason).
https://github.com/BuilderIO/qwik/issues/4210
And I saw couple of other threads about it:
#1107171415880384522
Basically, if something mutates the state during SSR, the result most of the times is not what you would expect.
One could argue, that mutating state on the server is an anti-pattern (AFAIK Next.js and React Server Components does not even support it).
But Qwik is different in a sense that some code is kind of blended together (e.g., useTask$ can run both on server and client), so IMO it should be fixed.
Yes, if I understand correctly you are mutating the signal after it has been rendered. Because Qwik streams, there is no way to go back and fix the mutation. So this is an anti-pattern.
But what if instead of "going back", Qwik committed those mutations to the client at the end of the stream? (as a script tag maybe?)
Not sure if that would cause some de-optimizations, but it's better than disregarding mutations completely.
So so thing like that would be possible with out of order streaming coming later. For now we have to stick to streaming constraint.
Sorry, I was unable to understand the resolution. What is the alternative in the case of the op issue? If I make a fetch inside getResource and need to transform the data returned and have it update the screen, what is the correct pattern to do so? As you can see from the example link, the approach using usetask and the store didn’t work.
You can do all the transformations inside useResource$(). And put all the components inside the <Resource onResolved={ ... here ...}> , since they depend on that value.
If you absolutely must use those values outside of <Resource /> , then as an escape hatch you can update in useVisibleTask$().
Example of both approaches: https://stackblitz.com/edit/qwik-starter-ozexgh?file=src%2Froutes%2Findex.tsx