S
SolidJS3mo ago
Gaba

how to use createAsync to feed createSignal

How should i guarantee that my signals are initialized AND fed with the Acessor from createAsync, while using <Suspense> ? The documentation doesn't make clear how the Acessor created by createAsync interacts with createSignal. Will the createSignals correctly intereact with <Suspense>? Which one of these two solutions would be the correct/recomended?
const { id } = useParams<{id: string}>();
const queryAcessor = createAsync(() => fetchSomething(id));
const [value, setValue] = createSignal(queryAcessor()?.data?.value);

return <Suspense fallback={<LoadingSpinner />}>
{tileRadius()}
</Suspense>
const { id } = useParams<{id: string}>();
const queryAcessor = createAsync(() => fetchSomething(id));
const [value, setValue] = createSignal(queryAcessor()?.data?.value);

return <Suspense fallback={<LoadingSpinner />}>
{tileRadius()}
</Suspense>
or
const { id } = useParams<{id: string}>();
const queryAcessor = createAsync(() => fetchSomething(id));
const [value, setValue] = createSignal();

createComputed(() => {
const data = queryAcessor()?.data;
if(!data) return

setValue(data.value)
})

return <Suspense fallback={<LoadingSpinner />}>
{tileRadius()}
</Suspense>
const { id } = useParams<{id: string}>();
const queryAcessor = createAsync(() => fetchSomething(id));
const [value, setValue] = createSignal();

createComputed(() => {
const data = queryAcessor()?.data;
if(!data) return

setValue(data.value)
})

return <Suspense fallback={<LoadingSpinner />}>
{tileRadius()}
</Suspense>
7 Replies
bigmistqke
bigmistqke3mo ago
The recommended way would be not to synchronize the accessor of createAsync with a signal, but use what createAsync returns directly: it's already a signal! And no: signals that are set by async signals/resources will not interact with suspense. But memos/derivations do.
Gaba
GabaOP3mo ago
But i need to be able to update the signal after initializing it with a async fetcher. Like, the external API will return the initial values, then, the component will have buttons to change the value (the signal) locally. But createAsync doesnt return a Setter... So how can i have a signal and a setter, where the initial value is set with an async function?
For more context: i'm building a page that will edit an RPG map, the fetcher will get the current map settings from a database, then the user must be able to change those values locally, so it finally submit the changes and update the database;
quick question: i know about memos, but what would be a "derivations" ? you mean derived signals like this?
const asyncSignal = createAsync(() => fetch())
const derivedAsyncSignal = () => asyncSignal().someValue
const asyncSignal = createAsync(() => fetch())
const derivedAsyncSignal = () => asyncSignal().someValue
bigmistqke
bigmistqke3mo ago
Gotcha. Now i understand the usecase better. Currently solid does not have dedicated API for that usecase, but this will change in solid 2.0. To mock the future behavior you can use this implementation:
function createWritable<T>(fn: () => T) {
const signal = createMemo(() => createSignal(fn()))
const get = () => signal()[0]()
const set = (v: any) => signal()[1](v)
return [get, set] as ReturnType<typeof createSignal<T>>
}
function createWritable<T>(fn: () => T) {
const signal = createMemo(() => createSignal(fn()))
const get = () => signal()[0]()
const set = (v: any) => signal()[1](v)
return [get, set] as ReturnType<typeof createSignal<T>>
}
With createWritable (and createSignal in solid 2.0) you pass an accessor to a signal instead of a default value. The signal can then be updated either by setting the setter, or when the passed accessor is updated. Usage:
const userResource = createAsync(() => fetch(...))
const [user, overwriteUser] = createWritable(result)
return <Suspense>{user()}</Suspense>
const userResource = createAsync(() => fetch(...))
const [user, overwriteUser] = createWritable(result)
return <Suspense>{user()}</Suspense>
createWritablewill trigger suspense any time the resource updates, but it will not be triggered when you call overwriteUser. + resource is what solid calls an async signal: what createAsync or createResource return yes, pretty much. a derivation is a memo, but without the memoization:
const [value, setValue] = createSignal(0)
// derivation, will be calculated everytime it is called
const double = () => value() * 2
// memo, will only be calculated when value() is updated
const doubleMemo = createMemo(() => value() * 2)
const [value, setValue] = createSignal(0)
// derivation, will be calculated everytime it is called
const double = () => value() * 2
// memo, will only be calculated when value() is updated
const doubleMemo = createMemo(() => value() * 2)
Gaba
GabaOP3mo ago
Cool! Thank you so much. Quick question: why is it called createWritable instead of something like createAsyncSignal ?
bigmistqke
bigmistqke3mo ago
ur very welcome!
why is it called createWritable instead of something like createAsyncSignal ?
I called it that because that's what it was originally going to be called in solid 2.0, before ryan decided that all signals will going have this behavior. There is nothing async about createWritable, you can use it for any signal that you want be automatically updated if another signal changes. As you can see in the implementation, it's like a memo and a signal combined, so you can even use it for memos that you want to be overwritable:
const [value, setValue] = createSignal(1)
const [double, overwriteDouble] = createWritable(() => value() * 2)
const [value, setValue] = createSignal(1)
const [double, overwriteDouble] = createWritable(() => value() * 2)
p
p3mo ago
funny i just came here for this exact question. glad I was able to find an answer. Do we have a timeline for solid 2.0 that you know of?
bigmistqke
bigmistqke3mo ago
Happy I could help! Regarding timeline: not sure really. I think a lot of the pieces are there, but Ryan mentioned in his last stream that they might go in a different direction for the signal implementation, so I can imagine this will add some time.
Ryan Carniato
YouTube
So Long Silicon Valley!
It's been 5 years now, but I'm moving to Portland, Oregon. So this will be my last stream from San Jose. We'll catch up on my latest reactivity work, the lat...

Did you find this page helpful?