S
SolidJS3mo ago
jack

derived, but update-able, signal?

is it possible to have a piece of reactive code that can be updated directly, but is also tied to another piece of state? I have a list I fetch from server that is wrapped with createAsync. I want to use this to track server state, but then have a dup of that list that can be updated any number of times in the app. The user then hits save, and we update the list on server and revalidate I originally just tried a derived signal, but I can't directly update this. Then I was thinking of just making another signal and having it's initial value be a call to its initial value, but I'm not sure if this is a good thing to do any idea?
26 Replies
Brendonovich
Brendonovich3mo ago
createWritableMemo from solid primitives should do what you want This is also how createSignal might work in solid 2
jack
jack3mo ago
could you expand on the second part? i will probably use the writableMemo, thank you should i be worried about memo'ing this if it's not a very intensive operation though?
Brendonovich
Brendonovich3mo ago
nah since you need to store a copy of the data anyway to overwrite yourself in solid 2 createSignal may allow something like this
// only updates when setValue is called
const [value, setValue] = createSignal("");

// updates when setValue is called OR when props.value changes
const [value, setValue] = createSignal(() => props.value);
// only updates when setValue is called
const [value, setValue] = createSignal("");

// updates when setValue is called OR when props.value changes
const [value, setValue] = createSignal(() => props.value);
jack
jack3mo ago
oh interesting so it tracks for reactive updates in the scope passed to createSignal?
Brendonovich
Brendonovich3mo ago
yeah
jack
jack3mo ago
that would be neat it's kind of a weird situation moving from react -> solid because a lot of things behave more naturally, but then a small handful of things that are super ergonomic in react feel harder in solid because everything doesn't get torn down and rerendered not actually sure if this is one of those situations now that i think of it, but i built this same app in react and didn't run into this for whatever reason
Brendonovich
Brendonovich3mo ago
iiirc react's advice for writable derived state is to setState during render right?
jack
jack3mo ago
I probably was doing it wrong tbh now i'm thinking back, i think my server state was in react-query, and i passed it as initial props to another piece of state, so i'd have client state in the hook, and then cache from RQ. Then when RQ updated the state would reset back to initialState from RQ update: don't think createWritableMemo plays well when derived from a createAsync 🙃 Which I guess sort of makes sense for some reason
Brendonovich
Brendonovich3mo ago
it evaluates eagerly so if you want to use Suspense you need to place it above where you call it, rather than below idk if that's your issue or not
jack
jack3mo ago
I call it in a parent and pass it to a child, which lives inside a suspense although, even if i don't pass it down, the presence of it in my component seems to defer rendering I have to try and trim down this code, 1 sec
Brendonovich
Brendonovich3mo ago
yeah bc it evaluates inside the component you call it in, not where you use it, that's the 'eagerly'
jack
jack3mo ago
oh when you said i need to place it above, i thought you meant the memo, not the suspense
Brendonovich
Brendonovich3mo ago
ah nah sorry
jack
jack3mo ago
i understand oof this isn't very fun, so there's no way for me to use it as lifted state essentially, if i need it where i have it now i'll need context i think ?
Brendonovich
Brendonovich3mo ago
something like that, lazy memos are tricky atm
jack
jack3mo ago
so just so i can understand properly, what is it about this that the eager evaluation that defers the render of the whole component ?
Brendonovich
Brendonovich3mo ago
suspense is triggered by accessing the async value. usually that would happen inside jsx so you can use a suspense in the same component, but memos access the async value in the component body, so the suspense needs to be above the whole component
jack
jack3mo ago
oh so in this case, the suspense i'm using can't track that it's been accessed i still don't get why it holds up the whole component, is that just default behavior for createAsync then ?
Brendonovich
Brendonovich3mo ago
it's specifically because the async value is being called inside a memo, and thus inside the component body. you can think of it like this
const asyncValue = createAsync(() => ...);

asyncValue();

return <div>{asyncValue()}</div>
const asyncValue = createAsync(() => ...);

asyncValue();

return <div>{asyncValue()}</div>
as soon as asyncValue gets called it looks up the ownership chain for a suspense and activates it
jack
jack3mo ago
and since there's no suspense above, there's no fallback, and nothing to show
Brendonovich
Brendonovich3mo ago
if there isn't one there then yeah
jack
jack3mo ago
yea I guess i can like sort of avoid it by just wrapping parent layout with suspense, but i get a really awkwardly brief blank page before the suspense i actually designed for in my current component kicks in
Brendonovich
Brendonovich3mo ago
you should be able to force the response to be paused by setting deferStream on the createAsync
jack
jack3mo ago
i think suspending in the layout is probably a bad idea then i get different behaviors on navigation vs refresh, i assume because in one case the layout is re-run, in the other case it's not oh yea deferStream just fixes everythng for the most part at least
Brendonovich
Brendonovich3mo ago
i'll work for first load at least
jack
jack3mo ago
on page reload i see nothing, but on client nav i get my suspended ui nvm i'm stupid and i was testing on a new page i made for debugging 🤦‍♂️. this is a tomorrow problem, not a 3 am problem
Want results from more Discord servers?
Add your server