S
SolidJS•7mo ago
smushball

Await a resource inside a function?

This there a function which achieves something similar as my fictional "waitForResource" function here? Or should I refactor my code?
const myResource = createResource(...)

const handleSubmit = async () => {
const data = myResource(); // T | undefined

const data = await waitForResource(myResource()); // T
}

return (
<form onSubmit={handleSubmit}>...
const myResource = createResource(...)

const handleSubmit = async () => {
const data = myResource(); // T | undefined

const data = await waitForResource(myResource()); // T
}

return (
<form onSubmit={handleSubmit}>...
29 Replies
deluksic
deluksic•7mo ago
If you do this under a transition, you can await an empty startTransition() call. It resolves when all resources resolve. I did not test this.
bigmistqke
bigmistqke•7mo ago
What is the usecase? Conditional rendering you could do w <Show/> or <Suspense/>.
smushball
smushballOP•7mo ago
Unsure how to use the startTranstition in this case. I need to use from data from my resource inside a submit callback. Specifically, it's like an "Add to cart" function, which needs to check some logic based on your cart, and a resource which fetches from some external API
bigmistqke
bigmistqke•7mo ago
I think this is what you are looking for
return (
<Show when={myResource()} keyed>
{
(data) => ...
}
</Show>
)
return (
<Show when={myResource()} keyed>
{
(data) => ...
}
</Show>
)
data in this case will be T without keyed data will be Accessor<T>
smushball
smushballOP•7mo ago
You would then pass data to the handleSubmit function?
bigmistqke
bigmistqke•7mo ago
yes exactly onSubmit={e => handleSubmit(e, data)} or something
smushball
smushballOP•7mo ago
Aight Ty
bigmistqke
bigmistqke•7mo ago
ur welcome!
deluksic
deluksic•7mo ago
Thing is that the user now must wait for the resource to finish loading before clicking the button. Slightly different feel depending on how long that resource takes. Could be just fine if <1s
bigmistqke
bigmistqke•7mo ago
Sure. But that was the behaviour of the original snippet, right? And sometimes that's exactly what we want. Just like Suspense, u can decide where u draw the boundary of what is and isn't rendered.
deluksic
deluksic•7mo ago
Original snippet rendered regardless of the resource being ready I believe. But if it solves the problem for OP, this is much simpler and preferred way, for sure!
bigmistqke
bigmistqke•7mo ago
ooo ur right i misread the code my bad
smushball
smushballOP•7mo ago
I would rather have an await resource() function, but sending the data from a Show callback is fine. It's more of a TypeScript issue
deluksic
deluksic•7mo ago
Ill see if I can make a startTransition work in playground, but only much later today
smushball
smushballOP•7mo ago
Would be awesome if it were possible 😄
bigmistqke
bigmistqke•7mo ago
I played around a bit with the idea for a waitForResource: https://playground.solidjs.com/anonymous/f767499f-81c2-4c81-8f02-36e1f2b25177
Solid Playground
Quickly discover what the solid compiler will generate from your JSX template
smushball
smushballOP•7mo ago
Yup, that seems to do it
bigmistqke
bigmistqke•7mo ago
tweaked it a little bit: https://playground.solidjs.com/anonymous/1ec29bf5-a0e8-4e07-a925-38e3915ab6fd the previous version wouldn't resolve if the promise returned a falsey value.
Solid Playground
Quickly discover what the solid compiler will generate from your JSX template
bigmistqke
bigmistqke•7mo ago
but ye i think u can get the main idea
smushball
smushballOP•7mo ago
Yup. I was just refactoring into the same ish thing Would be nice if Solid had a resource.promise() which resolved into the resource, but this function works well 😄
bigmistqke
bigmistqke•7mo ago
I agree. Kind of surprised nobody made a suggestion for it on https://discord.com/channels/722131463138705510/1085604933849595924 yet
bigmistqke
bigmistqke•7mo ago
Beauty of solid is that u can always make ur own wrapper if u really want that behavior https://playground.solidjs.com/anonymous/b4501633-864d-4de9-9f4e-562bab461e18 But now I made it I can see where this strategy fails, whereas regular resource doesn't: What if the fetcher is called again before the previous promise has been resolved? You are then awaiting an out-of-sync promise and end up with incorrect data. <Show/> and that waitForResource-helper would just wait for the second promise is resolved.
Solid Playground
Quickly discover what the solid compiler will generate from your JSX template
smushball
smushballOP•7mo ago
I think that depends on how Solid createResource works? Does it cancel the running promise when calling refetch ?
bigmistqke
bigmistqke•7mo ago
this visualises a bit what i was talking about
bigmistqke
bigmistqke•7mo ago
left the waitForResource, right with .promise
smushball
smushballOP•7mo ago
Makes sense
cirilla
cirilla•7mo ago
this maybe?
resource.promise = async () => {
while (true) {
const p = promise;
try {
const result = await promise;
if (p !== promise) continue;
return result
} catch (error) {
if (p !== promise) continue;
throw error;
}
}
};
resource.promise = async () => {
while (true) {
const p = promise;
try {
const result = await promise;
if (p !== promise) continue;
return result
} catch (error) {
if (p !== promise) continue;
throw error;
}
}
};
bigmistqke
bigmistqke•7mo ago
nice
peerreynders
peerreynders•7mo ago
I'd say that the use case for a waitForResource is ultimately a misguided extension of the sequential illusion confusion prevalent in async JS development; i.e. an async click handler is a red flag to begin with. Also SolidJS manifests simple is better than easy and waitForResource smacks of convenience over correctness. Fundamentally createResource and it's 2.0 replacement createAsync are gateways from the async world into the sync reactive world- a transfer point from async events to synchronous reactive state. So once you are on the left side of a resource (or createAsync) you should be using reactive idioms. If you wish to exit from the reactive graph back into the async world then do so via an effect. - The button could be clicked before the resource is ready. Let's say the UX is better if the button can be clicked before the resource is ready because the convenient solution would be to simply disable the button until the resource is ready. - There is nothing in the OP that prevents the button from being spammed, effectively launching multiple, concurrent submissions; the handler being async suggest the sequence of operations is relevant so at the very least the button should be disabled once it has been clicked, and only re-enabled once the sequence of operations has completed. In other scenarios it may be necessary to queue each submission click with any data that should captured at the time of the click while other data is only added when it finally has its turn executing its sequence of operations. So my solution looks quite a bit different: https://playground.solidjs.com/anonymous/a6712ce2-5661-482c-b994-9b698f1aa537
Solid Playground
Quickly discover what the solid compiler will generate from your JSX template
SolidJS
Solid is a purely reactive library. It was designed from the ground up with a reactive core. It's influenced by reactive principles developed by previous libraries.
Want results from more Discord servers?
Add your server