Error handling with chained resources.

Hello, I'm facing a problem with a chained "createResources". In a normal case, everything works fine. However, if the first fetcher throws an error, the error is not caught, which breaks the reactivity.
const [getId, setId] = createSignal(1);
const [song] = createResource(getId, fetchSong);//breaks if fetchSong throws
const [artists] = createResource(() => music()?.id, fetchSongArtists);
const [getId, setId] = createSignal(1);
const [song] = createResource(getId, fetchSong);//breaks if fetchSong throws
const [artists] = createResource(() => music()?.id, fetchSongArtists);
Here's the code. (without the http requests) https://playground.solidjs.com/anonymous/373405e2-5ce0-440b-b346-e94a8a403b56 In this example, if fetchSong() throws, the page get stuck in loading state instead of being in error state. Note: i would like to fetchSongArtists to be called only if the song is successfully loaded. I temporarily fixed this with a second signal and a createEffect, which is pretty ugly. How can i fix this? Is using multiple createResource in a component a good practice?
Solid Playground
Quickly discover what the solid compiler will generate from your JSX template
26 Replies
bigmistqke
bigmistqke2w ago
could you describe the expected behavior?
bigmistqke
bigmistqke2w ago
bigmistqke
bigmistqke2w ago
Is using multiple createResource in a component a good practice?
yes, I do it often too when i want to chain multiple async stuff together. it is a waterfall, which is mb not ideal bc there are multiple roundtrips from client to server.
POL SMOKE
POL SMOKEOP2w ago
If id become 0 , fetchSong throw And isn't caught
bigmistqke
bigmistqke2w ago
a i see yes i think the throwing is from where the resource is being initialised and not where it is being accessed it's a bit inconsistent with how suspense works
bigmistqke
bigmistqke2w ago
bigmistqke
bigmistqke2w ago
Solid Playground
Quickly discover what the solid compiler will generate from your JSX template
bigmistqke
bigmistqke2w ago
a but it is kind of interesting that when song throws it does not happen i don't really have an explanation for that
POL SMOKE
POL SMOKEOP2w ago
yeah, I don't know why the error is caught by the errorBoundary and not the ressource itself....
bigmistqke
bigmistqke2w ago
ye and when u comment out artists it also does not happen
bigmistqke
bigmistqke2w ago
aaaaaa i think i know it's const [song] = createResource(getId, fetchSong); this line that throws and there is no error boundary around that this was an incorrect statement, it does throw where it is being accessed.
POL SMOKE
POL SMOKEOP2w ago
?
bigmistqke
bigmistqke2w ago
yes, this is the rule i think, deducting the playground: whenever the getter of a resource throws, it is not caught by the resource. so that's why, when you comment out the const [artists] = ... when song errors, it does not crash the app.
POL SMOKE
POL SMOKEOP2w ago
So, fetchSong must not throws at all?
bigmistqke
bigmistqke2w ago
oops ment const [artists] = createResource(() => song()?.id, fetchSongArtists); this line
bigmistqke
bigmistqke2w ago
Solid Playground
Quickly discover what the solid compiler will generate from your JSX template
bigmistqke
bigmistqke2w ago
you could move the resource inside the error boundary
POL SMOKE
POL SMOKEOP2w ago
hooooo, i seee. And it means the error is not accessible by song.error
bigmistqke
bigmistqke2w ago
ye you will have to be a bit conscious about those getter-callback that can throw i never really came across this myself
POL SMOKE
POL SMOKEOP2w ago
HOOO, and using a try catch in the getter seems to work perfectly. https://playground.solidjs.com/anonymous/dc26daf8-d3a4-4f96-b4bf-d83a6704721c
Solid Playground
Quickly discover what the solid compiler will generate from your JSX template
bigmistqke
bigmistqke2w ago
nice!
POL SMOKE
POL SMOKEOP2w ago
thank you very mutch!!!
bigmistqke
bigmistqke2w ago
you are very welcome!
POL SMOKE
POL SMOKEOP2w ago
Ok, i see clear now. The state of the previous resource must be checked before calling its getter. So the artists resource finally look like this:
const [artists] = createResource(() => song.state==="ready"?song()?.id:undefined, fetchSongArtists);
const [artists] = createResource(() => song.state==="ready"?song()?.id:undefined, fetchSongArtists);
bigmistqke
bigmistqke2w ago
that makes sense then it will only call the resource when you are sure that it didn't error
mdynnl
mdynnl2w ago
i remember trying to fix this kind of error by changing the order of error and state being set but in practice we can't really rely on the order of execution
Want results from more Discord servers?
Add your server