Suspending or creating a resource from a Signal
I'm new to solid and trying to integrate it with Dexie. I looked at solid-dexie (https://github.com/faassen/solid-dexie) but I have a couple issues with it so I'm exploring taking it in my own direction. One problem, however, has me stumped.
Dexie exports an observable that is easy to link into with
from
. My issue is that there is a (very short) period between when the signal is defined and when it actually has a value. After that, it's guaranteed to have a value, and the signal fires repeatedly thereafter whenever the db content updates.
This means that I have to litter my code with <Show>
tags to check if each Dexie query I make actually has content. If only there was a way I could wait for all my signals to have content before I render anything.
Enter Suspense, or so I thought. My problem is that the Dexie queries aren't really a resource (they are signals that can fire multiple times, whereas a resource fires only on demand). I'm not clear if it's safe or sane to return a signal from a resource, but it seems to lack elegance.
So I checked the createResource source code and decided that I really just need to increment
and decrement
the suspense context at just the right time. The problem with that idea is that a very intelligent person realized that it would be imprudent to allow yahoos like me to increment
and decrement
the suspense context. Therefore getSuspenseContext
isn't exported.
Soooo... I'm looking for advice. Is there an elegant way to tie an observable signal to suspense using createResource or otherwise?18 Replies
One thing I thought might work was using my signal to trigger the resource by passing it as
source
to createResource
, but the resource then returns undefined until the signal initially fiers, which brings me right back to needing <Show> all over.Ye a resource is just a wrapper around an async signal, right. So you could return a promise that you resolve once it is defined and then you can count on Suspense to do its thing.
It will still be typed
undefined
in the beginning so you might still have to ! at some placesHah, I just seconds ago got that working, though it.... lacks elegance: https://gist.github.com/dusty-phillips/dde181bbbe887598e576abd32a429c62
well that's nice and readable. 😕 I'll get a gist, one sec.
Idk if u know https://playground.solidjs.com
Solid Playground
Quickly discover what the solid compiler will generate from your JSX template
oooh
My favourite repl
With createResource you can also map it directly to a store/deepSignal
not sure I understand.
https://docs.solidjs.com/references/api-reference/basic-reactivity/createResource#v150
See 3.
A wait, that mb doesn't work with the observable
What in ur gist u don't like?
Tip for the playground: you can import any npm package and it will import them from cdn
Main thing I don't like is the "single-use" createEffect, and I'm not sure if trigging the promise off the store itself changing is sensible.
In fact I don't need to trigger off the signal; I've simplified a bit. I'll see if I can get Dexie loading in the playground to demo.
maybe something like https://playground.solidjs.com/anonymous/8e2f7086-5c37-42ef-b4f8-cfb87b485d9a ?
Solid Playground
Quickly discover what the solid compiler will generate from your JSX template
i do wonder if the effect inside the promise gets cleaned up when it's resolved
Odd... I'm getting a console error "The requested module 'solid-js' does not provide an export named ResourceReturn.
A ye it's that new node rule where u have to do
import { type ...
Module resolution thingyah, yes.
Yeah, here's a demo with it working with a form:
https://playground.solidjs.com/anonymous/6ef86395-7a53-4473-a038-98ad1df25255
(it renders the fallback until something is added to the db, though)
I m outs right now but will look once I get back
As far as I can see, it's not possible to tell if Dexie's liveQuery is returning undefined because it doesn't know yet vs because there is no response.
I assume that the first undefined response is because it doesn't know yet and subsequent ones are ecause it's actually undefined.
I tried to hook something up that tracks whether the subscriber has been hit before, but now I've lost reactivity: https://playground.solidjs.com/anonymous/a350db31-2daf-4717-90d6-29a4eed2d8e6
I'm pretty sure it's because I'm resolving
store.value
now instead of resolve(store) (because I moved the value into the store).https://playground.solidjs.com/anonymous/353d8150-30a6-4d4a-951b-e25c3240500f hope it gives you an idea
aaah, it never crossed my mind to subscribe directly to the observable instead of immediately wrapping it in a signal. Thank you so much.
oh sweet, tested and it works with arrays and primitives out of the box with one unified syntax. Love it.