how do people manage state with rum? I'm now mostly using a single global atom + rum/reactive + cursors, but this seems pretty much equivalent to reagent
@chrisblom Datascript is awesome
How do you let specific components update based when the db changes? With cursors its really easy to subscribe to a specific part of the app state, how do you do this with datascript?
@chrisblom You can't currently. I think right now you have to do a full re-render. I have a fork of datascript that I want to publish within a few months that allows exactly that (pretty similar to MobX if you know that, but fully normalized due to Datascript).
cool, that would be really useful
so that would be similar to om-next's idea of subscribing to updates via queries?
but with a nicer way to store the state
Yeah slightly similar, but much much simpler. You don't have to write any queries, it's all done automagically
You only deal with Entities (whcih are just like maps) and if you access some attribute, it gets recorded and triggers a re-render of the Component once this attribute changes.
cool, thats sounds nice, i like the ideas behind om-next (unified data model, subscribe by queries), but in practice i find writing parsers & reconciling etc too complex
Yeah I had the same problem. I actually started out with om-next but switched pretty soon. I'm pretty happy with the framework. I have this todo list which would properly implement a few other things, but maybe I'll just release it without implementing my todo-items. I have had this for over a year and really need to put it out there.
The idea is similar to the datascript+rum examples of tonsky. He specified when to re-render in the components.
cool, i'd like to try it out sometime
https://github.com/tonsky/datascript-menu/blob/master/src/datascript_menu.cljs#L57-L70
@rauh @chrisblom What problems do you find just using cursors? Maybe I’m missing something about datascript (which I’ve never used) but it seems to me creating a cursor is sort of like expressing a subscription.
(A related question I’ve been meaning to investigate is whether you could just alter get-in to pay attention to the data path you specify. If it can do it with cursors, why not accesses?)
cursors are limited to a sub-tree of the app state
though you can work around this by using derived-atom
also i find myself passing around multiple cursors to a component
I don't like cursors. I have used it once in my code base and a few months later refactored it into callbacks.
for example, for a list element with a 'delete' button, I now need to pass a cursor the element, and a cursor to the list so i can do something like (swap! list-ref dissoc (:id @element-ref))
on click
@rauh i must be dense. how do you replace a cursor with a callback?
IMO, and this is more general: I think state that is complex/nested isn't well expressed with maps + vectors. In general state is a graph. Ie. we absolutely need a graph database to stay sane. And that's why I use datascript which allows me to just walk the graph in any direction as I want to. By walking a graph you create a tree. Which is exactly what HTML is. So it's very natural.
That's also the entire idea of keeping your state completly normalized, which is preached by Redux folks + om-next. Which totally makes sens. But I don't want to do this by myself when there already is a DB (datascript) that keeps my complete state maximally normalized (E A V, datoms)
yeah i agree, i also don't like this aspect of om-next
@lee.justin.m Instead of passing a cursor down, which is swap!
'd I just ask for a callback to be invoked when it wants to make changes to a state. Works well with up to 2-level deep but then it becomes awful.
oh got it
Sometimes when I read about all of these tools and all of this terminology I feel like we overthink things and I wonder if I’m missing something so it is really good to hear your experiences.
So far for me cursors are simple (if verbose) and behave in a predictable way.
But I totally see the points you guys are making.
FWIW, I don't write any queries in Datascript (I threw out the entire query engine). I only use Entities and I walk along them, just like a CLJS map. So the API is very much like maps/vectors but the db is just one long normalized index (EAV, plus the other indices)
I really liked mobx in javascript but I found that it was too easy to break it and totally impossible to debug. So then I went to redux, which is great, but has so much boilerplate that you need a type system to manage it. Now I’m here, having tried reagent, om, om-next… I like it so far.
Yeah I don't love MobX in general. If I were to do JS I would choose MobX state-tree probably. It got a lof of stuff right. It's the closes to a graph database. Unfortunatly not as flexible as Datascript however. No custom indices and you're constraint with your attributes.
I don’t think it’s ever going to be predictable until proxies make it into the browser
what’s awesome about clojurescript is that you already have a layer of indirection at the lowest level of data access. it’s like the language was built to solve all of these state management problems
Yeah I have a few answers for that. In my framework I can query a component in the REPL and it will exactly tell me what Datoms it uses to render. So it's pretty simple to understand.
ooh that’s nice
while you guys are here: I just adapted react-dnd to rum. if you aren’t familiar, it uses decorator syntax, so you do something like export default DragDropContext(Backend)(MyApp)
to decorate your top-level component. I did this using a mixin to wrap the actual react component and return an altered state. This seems like it is working, but is there a better way of doing HOCs?
Haven't used it but I'd say mixins is probably the right answer here.
@justinlee i actually prefer cursors like 90% of the time, easy to understand and debug, its the 10% of more complex cases that i'm looking into
in my experience most of the time state is a tree, so cursors are fine in those cases
@chrisblom When the tree state of your app-db is ill-suited to your rendering needs, consider https://github.com/martinklepsch/derivatives