peerreynders
peerreynders
SSolidJS
Created by all_is_source_energy on 3/12/2025 in #support
Different routes using different layouts, while doing file based routing please?
src/routes/(one).tsx
src/routes/(one)/a.tsx
src/routes/(two).tsx
src/routes/(two)/b.tsx
src/routes/(two)/c.tsx
src/routes/(one).tsx
src/routes/(one)/a.tsx
src/routes/(two).tsx
src/routes/(two)/b.tsx
src/routes/(two)/c.tsx
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
SSolidJS
Created by gsoutz on 3/10/2025 in #support
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
SSolidJS
Created by gsoutz on 3/10/2025 in #support
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
SSolidJS
Created by Garrett Floyd on 3/6/2025 in #support
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
SSolidJS
Created by Garrett Floyd on 3/6/2025 in #support
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 actions revalidate all active querys. 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-7aaae485025a
12 replies
SSolidJS
Created by gsoutz on 3/10/2025 in #support
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 again
That is exactly the point.
const result = createAsync(async () => {
const data = await callDb(session());
console.log('here', data);
return data;
});
const result = createAsync(async () => {
const data = await callDb(session());
console.log('here', data);
return data;
});
This one flips from id 1 to 2 and back but these:
const result1 = createAsync(() => callDb(1));
const result2 = createAsync(() => callDb(2));
const result1 = createAsync(() => callDb(1));
const result2 = createAsync(() => callDb(2));
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-7aaae485025a
34 replies
SSolidJS
Created by gsoutz on 3/10/2025 in #support
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 createAsyncs will not cause a refetch. That can go on indefinitely, there is no time limit. The moment no createAsyncs 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
SSolidJS
Created by gsoutz on 3/10/2025 in #support
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:
const updateTodo = action(async (todo: Todo) => {
await putTodo(todo.id, todo);

return revalidate(getTodo.keyFor());
});
const updateTodo = action(async (todo: Todo) => {
await putTodo(todo.id, todo);

return revalidate(getTodo.keyFor());
});
revalidate is typically used outside of actions. In that particular example revalidateduplicates re-running of the query: 1. By default any action will revalidate all actively referenced querys on the page (i.e. they will all re-run). 2. If you want to narrow which querys run you have to use reload.
const updateTodo = action(async (todo: Todo) => {
await putTodo(todo.id, todo);

return reload({ revalidate: getTodo.keyFor(id) });
});
const updateTodo = action(async (todo: Todo) => {
await putTodo(todo.id, todo);

return reload({ revalidate: getTodo.keyFor(id) });
});
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
SSolidJS
Created by gsoutz on 3/10/2025 in #support
query function invalidates the cache every 10 clicks
the data is still considered 'fresh' for a short period
I'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 in createAsync vs preload
You are correct. When a 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
SSolidJS
Created by gsoutz on 3/10/2025 in #support
query function invalidates the cache every 10 clicks
As far as I have been able to determine by reading the query.ts code and verifying with various experiments, yes.
34 replies
SSolidJS
Created by gsoutz on 3/10/2025 in #support
query function invalidates the cache every 10 clicks
The data is considered fresh only for a short time yeah
There 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
SSolidJS
Created by gsoutz on 3/10/2025 in #support
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-39e7b6927ad6
34 replies
SSolidJS
Created by gsoutz on 3/10/2025 in #support
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
SSolidJS
Created by gsoutz on 3/10/2025 in #support
query function invalidates the cache every 10 clicks
34 replies
SSolidJS
Created by Eddie on 1/31/2025 in #support
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
SSolidJS
Created by Eddie on 1/31/2025 in #support
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
SSolidJS
Created by JonathanExcelsior on 3/9/2025 in #support
reconcile within produce
… so wrap 'em in batch?
5 replies
SSolidJS
Created by batman✅ on 3/9/2025 in #support
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
SSolidJS
Created by JonathanExcelsior on 3/9/2025 in #support
reconcile within produce
Both return an update function for the store, so in those terms no. What are you trying to accomplish? Maybe something like:
function upsertUser(user: User) {
const index = untrack(() => state.users.findIndex((u) => u.id === user.id));
if (index === -1) setState('users', (users) => [...users, user]);
else setState('users', index, reconcile(user));
}
function upsertUser(user: User) {
const index = untrack(() => state.users.findIndex((u) => u.id === user.id));
if (index === -1) setState('users', (users) => [...users, user]);
else setState('users', index, reconcile(user));
}
5 replies
SSolidJS
Created by gsoutz on 3/7/2025 in #support
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