Thanks!
What I did is to make a subscription to check if the database change.
So all my queries have a layer 3 subscriptions.
And since checking for equality of immutable data structure is cheap, it is fast enough.
Hence, queries will not be run again, unless the datascript db was modified.
Obviously, you might not want to have all your state variables in a single datascript database.
My issue was that my app started to have a lot of query logic and I was starting to repeat the same code all the time, and it become ever more convoluted when I had to make joins operations.
So to answer the critic: no, your queries will not be re-run whenever app-db change thanks to 3 layers subscriptions.
I've an app that needs to make a websocket connection for fetching data. I'm using re-frame-async-flow-fx with great success to orchestrate my initial app boot. Reitit is my router. Now, I have to handle cold-start on nested routes like /app/a-thing/1/a/nested/thing/42. The reitit controller functions dispatch "get my data" events when the route is loaded, but this happens in parallel to the boot flow, so often the boot isn't complete by the time the controller event fires, resulting in a failure to get data. Any tips on how to resolve this?
For now I've been re-queuing the controller event in the failure handler with dispatch-later π
Hmm, but then the boot flow would be triggered by the user just navigating in the app even in non-cold start scenarios
You can use a flag of sorts to check if it's a cold start or not.
Also I can't miss this opportunity to mention kee-frame. :) Maybe it'll be useful to you as well.
A first-boot flag would work I suppose, but the more I think about it I think this can be solved by solving the general case of retry-handling when the ws connection fails. I'm using sente, so auto reconnecting is built in, but when events fail due to a bad socket, I need a way to retry them once th connection is back up. Hm but you probably don't want to retry every request.
Make reitit start the boot flow?
Hmm, but then the boot flow would be triggered by the user just navigating in the app even in non-cold start scenarios
You can use a flag of sorts to check if it's a cold start or not.
Also I can't miss this opportunity to mention kee-frame. :) Maybe it'll be useful to you as well.
A first-boot flag would work I suppose, but the more I think about it I think this can be solved by solving the general case of retry-handling when the ws connection fails. I'm using sente, so auto reconnecting is built in, but when events fail due to a bad socket, I need a way to retry them once th connection is back up. Hm but you probably don't want to retry every request.
Thanks to @olivergeorge @mikethompson and others who https://github.com/day8/re-frame/issues/639 we have a new re-frame release v1.1.0 with a new :fx
effect. Read more at https://github.com/day8/re-frame/blob/master/docs/api-builtin-effects.md#ordering
Erm, sorry -- I meant datascript db. Posh actually watches the datom changes and will intelligently re-run subscriptions.
On a page refresh I am losing certain items from the app-db causing my page to blow up, are there any best practices around persisting things? I am also confused why somethings stick around and others vanish.
Nothing should stick around in app-db
by itself. Something somehow loads that data into app-db
from somewhere.
With that being said, the usual place to persist things client-side is Local Storage.
Essentially I have a list of tasks, when you select a task it opens a page that is subscribed to a task object in the app-db and the event sets the selected task to that. If I want refresh to not, blow up should I also be putting the task into local storage as well so if it is not already in app-db, I can pull it in?
If you're writing an SPA, why do you refresh the page? Why not just load data via XHR/WebSocket and use it while also updating the URL in the browser address bar?
That is what I am doing, but during development I am refreshing the page to see my changes and was wondering what to do if the user refreshes the page during some workflow?
> I am refreshing the page to see my changes You should change your development setup so that the page is re-rendered (not refreshed!) automatically when you make a change. Figwheel and Shadow-cljs support this. > was wondering what to do if the user refreshes the page during some workflow It depends on the workflow. Take what you want to achieve, find a conceptually similar platform that's used by actual users, and see what they've done. For example, GMail doesn't save anything but drafts. So a draft is part of its persistent state, but e.g. current email filter or even current app section (like inbox or settings) are not.
1Okay sweet, will check that out and sounds good will think that through! Thanks!
NP, good luck.
Fair point! I was also concerned, but then I think re-frame only recompile subscriptions that are relevant to the current view. So you would need to run the queries anyway?
Every time you transact data to Datascript, every single DS query will need to re-run even if the transaction did not affect the query.
Even if you donβt dereference to the subscription where the queries defined? Anyways, you can circumvent the problem by having multiple datascript datastore, posh forces you to have a single one.
But I will test whether all subscriptions are re run when if you transact.
If it is not in the view, it won't rerun. In a view with subscriptions, it is highly unlikely that a single DS transaction would affect every single subscription in the given view.
Yes, which minimise the risk of performance issues right?
No. Take this example... A view is showing the a user's email and a list of products. If you transact any data to Datascript, even if the data isn't relevant to your current view (e.g., you're updating some DS data behind the scenes or storing some internal data), every subscription in your current view will rerun. In a worst case scenario, you'd store the data from an input in DS. This would cause every single query to rerun with each keystroke.
Fair point. To that I answer: you can isolate the data for an input in a different DS in your re-frame app. Reposh forces you to have a single datastore.
But I see your point. I guess I can use posh as well.
I think my biggest issue was that re-posh does not integrate well with re-frame, the disadvantage of this method is that you need to manually partition the different DS databases inside your re-frame DB, and this will solve the performance issue.