peerreynders
Different routes using different layouts, while doing file based routing please?
https://docs.solidjs.com/solid-start/building-your-application/routing#route-groups
+
https://docs.solidjs.com/solid-start/building-your-application/routing#nested-layouts
6 replies
query function invalidates the cache every 10 clicks
If you are concerned about caching, people are usually happy with solid-query. On the other hand people who have worked with React Query often found that
query
's reference counting scheme was good enough but I don't think any of them were “local first”. Using dexie, dexie is your cache; what you are looking for is a sync engine.34 replies
query function invalidates the cache every 10 clicks
The question is why query invalidates the cache basically rendering it useless.Your starting premise was incorrect. -
query
is not a caching mechanism; it exists to de-duplicate fetches.
- Nothing got invalidated. Once your application de-references a fetch result, it is immediately considered “garbage”. Similarly while your application maintains a reference to the fetch result that fetch will not be repeated (indefinitely) even if it is referenced again.
Your example de-references the fetch result by switching from ID 1 to 2 and back—so each time it performs a fresh fetch. It is behaving as intended.
If you click it fast enough you run into an edge case. A recent query value has a 5 second window of “protection” from reloading. That time period has nothing to do with caching but it exists to enable route preloading.
If you spin up a fresh “basic” SolidStart template and replace src/routes/about.tsx
with this:
https://discord.com/channels/722131463138705510/910635844119982080/1349086371536572437
you can see how preloading works:
- Load the project on the /
page
- Hover over the link for the /about
page. The preload will fire and the query
will perform the fetch—exactly once; even though the hover event will fire multiple times.
- Finally click the /about
link. The app will navigate to the page and the createAsync
will finally reference the query
—and again there isn't another fetch because the fetch result is protected by that “5 second” window.
The above describes why the “5 second” reload protection window exists. It has nothing to do with “caching”, everything with preloads working in combination with fetch de-duplication.34 replies
How do you get createAsync to refetch or mutate?
As it happens I also threw together an example with preload today:
https://discord.com/channels/722131463138705510/910635844119982080/1349086382081183815
12 replies
How do you get createAsync to refetch or mutate?
However, this is not what I'm seeing.For that to work the actual fetch function has to be wrapped in a
query
.
An example I had from another topic:
https://playground.solidjs.com/anonymous/de1ecf9e-b57b-42cc-b3c0-39e7b6927ad6
And also by default action
s revalidate all active query
s. Given that you are already using an action
revalidation should “just work” provided the function used by createAsync
accesses the fetch result via a query
.
revalidate
version of the above without action
:
https://playground.solidjs.com/anonymous/ecfc76e8-3183-4298-8507-7aaae485025a12 replies
query function invalidates the cache every 10 clicks
it doesn't update, each time I reload the example. and it never hit's the database againThat is exactly the point. This one flips from
id
1 to 2 and back
but these:
are keeping a permanent reference to either result.
This means that as far as query
(a fetch de-duping mechanism) is concerned a refetch is never necessary. If you need to refetch, you use an action
(which by default reloads the route data) or you revalidate(callDb.keyFor(id))
.
https://playground.solidjs.com/anonymous/de1ecf9e-b57b-42cc-b3c0-39e7b6927ad6
https://playground.solidjs.com/anonymous/ecfc76e8-3183-4298-8507-7aaae485025a34 replies
query function invalidates the cache every 10 clicks
How can a user or Solid itself use the data during the period between PRELOAD_TIMEOUT and CACHE_TIMEOUT?You're looking at it from a(n expiry-time based) caching perspective. Get that out of your mind.
query
is a fetch de-duping mechanism.
While at least one createAsync
is referencing the value additional references from other createAsync
s will not cause a refetch.
That can go on indefinitely, there is no time limit.
The moment no createAsync
s are referencing that query
, the value is useless.
PRELOAD_TIMEOUT is just an tiny initial window where the value is protected from reloads while the are no createAsync
references.
CACHE_TIMEOUT is the age when the value gets purged entirely because nobody has a reference to it.
---
A fetch result held by a query
wrapper is considered valid as long as the application holds at least one (createAsync
) reference to it.
Once the last reference to the fetch result has been dropped, the result is considered invalid; i.e. the fetch result can disposed of and for the next , “first” new reference a query
re-run is required.34 replies
query function invalidates the cache every 10 clicks
So you are saying that revalidate revalidates the 'data in the cache'?Revalidating is the client-side logic telling the client side router that it just did something on the server that invalidates the associated client side
query
values.
That said the example given under revalidate
is bogus:
revalidate
is typically used outside of actions
. In that particular example revalidate
duplicates re-running of the query
:
1. By default any action
will revalidate all actively referenced query
s on the page (i.e. they will all re-run).
2. If you want to narrow which query
s run you have to use reload
.
2b. If you are returning a result from the action
use the options on json
. This is with the understanding that you can only obtain that result via the result
property from useSubmission.
3. The moment you narrow the revalidation keys
, you opt out of single-flight
(i.e. single flight wraps all the values for a route reload; unless something has changed recently).34 replies
query function invalidates the cache every 10 clicks
the data is still considered 'fresh' for a short periodI'm not denying the behaviour that you are observing, I'm challenging the interpretation. It's too easy to rationalize the “5 seconds” as some “freshness” feature. It's just an initial window to give the de-duping behaviour some time to get going. By design what is preventing
queries
from being reloaded is that they are still being referenced; while there is at least one single reference that behaviour can go on indefinitely.
Not re-running isn't linked to “freshness” but fetch de-duping.
I don't think the cache changes when it's executing inYou are correct. When acreateAsync
vspreload
query
loads it retains it's loading time no matter how the loading was initiated.
However the intent behind the 5 second
limit is so that pre-loading can get an early start on the fetch before the query
references of the page being wired up on the client side start coming in.
Could that 5 second
window prevent re-runs in some other edge cases? Sure. But those edge case aren't why that limit exists.34 replies
query function invalidates the cache every 10 clicks
The data is considered fresh only for a short time yeahThere really is no concept of “fresh”/“stale” with
query
; using these terms sets the wrong expectations with people.
1. When an unreferenced query
is referenced it will run.
2. When a referenced query
gets additional references it will not run (for fetch de-duping).
3. Loading of a query (e.g. preload
) is followed by a 5 second grace period during which referencing the unreferenced query
will not re-run it again.34 replies
query function invalidates the cache every 10 clicks
Accesses to
query
automatically starts a transition if it reruns. At least that is how it worked in past.
Ok, it seems that transitions are started on revalidation and on navigation.
https://playground.solidjs.com/anonymous/de1ecf9e-b57b-42cc-b3c0-39e7b6927ad634 replies
query function invalidates the cache every 10 clicks
Your example has two cache values:
-
-
query(id=1)
-
query(id=2)
Those cache values have reference counts and the time they were initially loaded. If the first createAsync
connects to the query
before the 5 second expiry then it will not rerun (de-duping for preloads).
And while the reference count to query(id)
remains above 0 additional createAsync
connects will not rerun either.
The moment the reference count goes to 0 and you are outside the intial 5 sec window it's game over- the next connect by a createAsync
will cause a rerun.
In your example you constantly swap between either value, letting the reference count of the other drop to 0. So once you are outside of the 5 second window it will invariably rerun.
In my example I make sure the reference count never goes below 1 so it never reruns.
The idea is that as long as you are holding a reference to that query
value, your application is actively managing the value, so it is responsible for revalidating the query
whenever an action modifies the remote value.34 replies
query function invalidates the cache every 10 clicks
Compare it to this one:
https://playground.solidjs.com/anonymous/a8bf69e5-f3dd-4755-843a-7bd421074925
34 replies
Hydration error when using <Show> in SolidStart
I guess I learned that everything async requires a suspense somewhere up the component tree.I seem to remember that it was mentioned somewhere that you need supense boundaries for SSR to work if you have async data sources. What wasn't mentioned was how it would fail.
12 replies
Hydration error when using <Show> in SolidStart
Are you by any chance passing
<Footer />
as a prop somewhere?
See:
https://discord.com/channels/722131463138705510/1238643925988937820
If so use () => <Footer />
instead.12 replies
Running BullMQ worker (background process) from a SolidStart project
The file worker.client.js
is calling various other modules which has use server directive set.
So the issue is that you are marking entire server modules as accessible by the client which as a consequence restricts their use on the server side.
I'd keep the server code in a plain modules and create separate modules for the "use server"
access points for client RPC.2 replies
What to do instead of loading a model with createMemo inside a createResource computation
Mutation is only enabled from the top level commands that are made available via
actions
which can be highly restrictive. And even though all actions are available to anyone with access to the context, it is much easier to trace “who's responsible for this state” as all mutations have to go through a fairly restrictive set of command functions.
I also see these command functions as being in the spirit of “Tell, don't Ask”; rather than just grabbing a hold of any fine-grained data/object and mutating it with impunity, using a dedicated command is “telling” (suggesting, really) the steward of the data what change is necessary (the steward having final authority on if and how that change will be implemented).
So the difference really is that getters and setters are always separate and setters only really exist on the primitive level. Mutations are only exposed as action commands at the top level, never below that, in order to make it easier to preserve unidirectional data flow.7 replies