Solid 2.0 async system design choices #2791
Replies: 2 comments 5 replies
-
|
Yeah, I don't like the decision to force pending state management into only |
Beta Was this translation helpful? Give feedback.
-
|
I see some bugs here that probably confusing the design a bit. 2. is most definitely a bug. IsPending shouldn't be erroring out, and only is responsible for propagating NotReady in the initial case. That being said both 1 and 3 probably deserve a more detailed response.
However,
There needs to be some educational content around this. It is really as primary as UI = fn(state) sort of thing. That in itself only describes the propagation side.. the GET/read side. The whole other half of the equation isn't represented. And its super important in understanding what isPending is. The sequence of events was we fixed Basically the key to propagation side is that it is always a snapshot of untorn state.. it where all our signal rules take effect. Every node runs once and in order, etc... which means it only knows that it is consistent not why. There is no time.. It could be updated because of 200 distinct changes for 200 distinct reasons but none of that matters. It just needs to produce the right results exactly once at a node level. Asking why has no business here. If you have some sort of process.. feel free to reseed an external source outside the system, clear a cache.. even use refresh to re-propagate on resolution but keep that stuff outside. If you want to know the status of your process use optimistic state. I realized that when resetting error boundaries. I'm at the point I'd call any function even state setters actions.. updating a value, resetting an error boundary, trigger refresh of part of the graph are all parts of actions.. the other half.
Using your example. A query client probably should subscribe to its key, or at minimum the invalidation of the cache can be pushed to where the call to revalidate. Ie clear cache before triggering refresh. |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
I want to ask some questions about the design choices that were made in Solid 2.0 regarding async resources.
isPendingcannot be used outside a Loading boundary for async resources? Shouldn'tisPendingbe able to be used anywhere in the tree? The below pattern is probably not uncommon - which always renders a button to refresh the resource - but doesn't work as expected:Workaround: try catch isPending to prevent it from throwing NotReadyError
isPendingis designed to cause render errors, instead of just returningtrueorfalsewhen the resource is pending or not? The below code is expected to render the button, even ifdatafails, since nothing breaks, but actually rendersErrored.And when I want to disabled the reset button in Errored fallback, the below doesn't work:
Workaround - not what I want but at least doesn't crash the app - is to use
<Loading on>to discard the Errored state:I couldn't find a way to safely subscribe to async data inside Errored fallback. The
isPendingSafeabove doesn't work because reading reactive values create dependency links which drive error state transitions directly without calling fn again.isRefreshinghas been removed in this commit 52255dc, then how do I tell whether the function increateMemois being recomputed as the result ofrefresh(resource)? I think a common use case for async createMemo is to use a separate query client / cache store likecreateMemo(() => client.query(userApi))instead of a directcreateMemo(() => fetch(userApi)). To integrate such query client with Solid's async system, I need to checkisRefreshing()(andisResetting()- if available) in thecreateMemofunction to decide whether to return cached data or to refetch. IMHO it's unlikely that one relies oncreateMemofor global state management / caching in bigger applications.The changelog mentions: "
refresh()is an action that invalidates an explicit refresh target; it should not expose ambient phase state to pure computations." Why is the function in createMemo considered pure computations? It likely interacts with external sources (that's why it's async) which means it's not pure. And "User-visible mutation or retry intent should be modeled with actions and optimistic state", but modeling refresh intents with optimistic states is probably more complex if the async resource is used in multiple places in the tree.The below pattern is common with query clients and would be more complex to implement with createOptimistic/createOptimisticStore:
The workaround for my case is to use dependency tracking between computations, to rule out known pathways that causes recomputations, and then
isRefreshing = deepStrictEqual(oldDeps, newDeps), but that's not ideal I think.It looks to me that those design choices result in somewhat... React-ish code - rules of primitives and dependency tracking. I'm new to Solid though so I might be missing something.
Beta Was this translation helpful? Give feedback.
All reactions