Fork me on GitHub
#rum
<
2018-01-17
>
chrisblom15:01:28

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

rauh15:01:47

@chrisblom Datascript is awesome

chrisblom15:01:37

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?

rauh15:01:49

@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).

chrisblom15:01:06

cool, that would be really useful

chrisblom15:01:52

so that would be similar to om-next's idea of subscribing to updates via queries?

chrisblom15:01:20

but with a nicer way to store the state

rauh15:01:33

Yeah slightly similar, but much much simpler. You don't have to write any queries, it's all done automagically

rauh15:01:18

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.

chrisblom15:01:13

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

rauh15:01:48

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.

rauh15:01:42

The idea is similar to the datascript+rum examples of tonsky. He specified when to re-render in the components.

chrisblom15:01:29

cool, i'd like to try it out sometime

justinlee16:01:26

@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.

justinlee16:01:23

(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?)

chrisblom16:01:47

cursors are limited to a sub-tree of the app state

chrisblom16:01:13

though you can work around this by using derived-atom

chrisblom16:01:38

also i find myself passing around multiple cursors to a component

rauh16:01:19

I don't like cursors. I have used it once in my code base and a few months later refactored it into callbacks.

chrisblom16:01:04

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

justinlee16:01:52

@rauh i must be dense. how do you replace a cursor with a callback?

rauh16:01:18

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.

rauh16:01:33

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)

chrisblom16:01:18

yeah i agree, i also don't like this aspect of om-next

rauh16:01:51

@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.

justinlee16:01:29

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.

justinlee16:01:59

So far for me cursors are simple (if verbose) and behave in a predictable way.

justinlee16:01:09

But I totally see the points you guys are making.

rauh16:01:36

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)

justinlee16:01:01

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.

rauh16:01:52

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.

justinlee16:01:21

I don’t think it’s ever going to be predictable until proxies make it into the browser

justinlee16:01:17

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

rauh16:01:01

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.

justinlee16:01:47

ooh that’s nice

justinlee16:01:43

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?

rauh16:01:42

Haven't used it but I'd say mixins is probably the right answer here.

chrisblom16:01:20

@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

chrisblom16:01:55

in my experience most of the time state is a tree, so cursors are fine in those cases

martinklepsch21:01:28

@chrisblom When the tree state of your app-db is ill-suited to your rendering needs, consider https://github.com/martinklepsch/derivatives