This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
- # babashka (19)
- # beginners (43)
- # calva (10)
- # clj-kondo (3)
- # cljsrn (8)
- # clojure (106)
- # clojure-europe (8)
- # clojure-hungary (5)
- # clojure-nl (1)
- # clojure-uk (1)
- # clojurescript (14)
- # core-typed (1)
- # graalvm (2)
- # graphql (1)
- # malli (2)
- # membrane (9)
- # observability (2)
- # off-topic (66)
- # polylith (3)
- # practicalli (3)
- # re-frame (17)
- # reagent (3)
- # remote-jobs (7)
- # rewrite-clj (17)
- # sci (29)
- # shadow-cljs (45)
- # sql (5)
- # tools-deps (15)
- # vim (8)
I’m new to reframe, and I was wondering, why would you not want to use re-posh (or datascript) as your app DB? Is there another way to get a normalized app state?
Is is possible to have a moderate sized app and still everything in datascript? including when you’re typing into an input field?
Or perhaps is the right technique to only store entities from the server in datascript and transient UI data in a simple shallow hash map i.e. the usual
I noticed this in the todomvc example https://github.com/day8/re-frame/blob/master/examples/todomvc/src/todomvc/views.cljs#L8
it's good practice to put state that is local to a component inside a local ratom, and store global state (like cached data from the server, or navigation state, or other such things) in the app-db
re: datascript, in my experience datascript is quite slow. I wrote https://github.com/lilactown/autonormal to normalize app data w/ re-frame
To expand a bit on what lilactown has said about local/global state.
app-db is for app's state. What you consider your app's state is up to you, but there are some facts that can help you decide:
app-db can be saved and restored as a whole
• Unless you try to do something clever by passing callbacks or atoms around, event handlers can only change
app-db it's relatively trivial to implement a global undo/redo mechanism. But local state won't be touched by that mechanism
app-db is monitored by such tools as
• Code reloading during development will erase any local state, but
app-db data will remain
Because of all that, I use local state only for throwaway data. Like e.g. a button with a simple yes/no confirmation dialog that's tied only to that particular button. Or mouse position for dialog movement calculations. Something like that.
Regarding datascript - I had the same experience with its speed as lilactown, although it was years ago.
Some other factors:
• The vast majority of queries in UI, at least in my applications, are simple and not different from a simple
select a, b, c from entities where some_field in (1, 2, 3); (using SQL just as lingua franca - I don't actually use it in UI). You don't need datascript for that.
• I really don't like namespaced keys in data that I fully control and know. One particular example - suppose I have 5 entity types that all have a
:name field with the same semantics and type. Without namespaces, I can write a single component to display that field. With namespaces, I must either write 5 components or write one that accepts the field name as a parameter, thus complicating things significantly.
At first I adopted subgraph, but I ended up writing my own implementation. It's not public though - there are things I'm still working on. For example, I find it extremely valuable to have a concept of what I call changesets when the library is used with re-frame. So if you get regular data as described by the above SQL query, you'd use something like
(get-data db ...). But if you need data that's been changed by a user but haven't been uploaded to the server yet, you use
(get-data db changeset-id ...). Each changeset is also able to store arbitrary data, using namespaced keywords this time - data that's relevant only to the changeset and must be discarded along with it but must not be used when saving it, like remote validation progress and results for example.
datascript is powerful, huge and slow. You usually don't need it, and it will usually be more of a pain than a help. there are many ways to get normalized db in cljs https://github.com/ribelo/doxa https://github.com/riverford/compound https://github.com/vimsical/subgraph https://github.com/juxt/pull
#fulcro is also something to consider when looking for the normalized database route that contains all appdata
Eric Normand has a great write up on where to store state in a re-frame app. https://purelyfunctional.tv/guide/state-in-re-frame/
One area where normalised data may be less desirable than it first appears is mutations away from your app. e.g. how much of your normalised data is fresh and how/when should you update it. If it might not be fresh then the data could still be useful for optimistic display of data but other use cases become problematic. You still want to check with the server when data is used in case it's stale.