rum

Simple, decomplected, isomorphic HTML UI library for Clojure and ClojureScript | 0.12.8 https://github.com/tonsky/rum/blob/gh-pages/CHANGELOG.md#0128
2018-01-17T15:04:28.000529Z

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

rauh 2018-01-17T15:19:47.001001Z

@chrisblom Datascript is awesome

2018-01-17T15:21:37.000429Z

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?

rauh 2018-01-17T15:25:49.000124Z

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

2018-01-17T15:27:06.000644Z

cool, that would be really useful

2018-01-17T15:27:52.000415Z

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

2018-01-17T15:28:20.000590Z

but with a nicer way to store the state

rauh 2018-01-17T15:28:33.000293Z

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

rauh 2018-01-17T15:29:18.000178Z

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.

2018-01-17T15:30:13.000253Z

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

rauh 2018-01-17T15:31:48.000065Z

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.

rauh 2018-01-17T15:32:42.000228Z

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

2018-01-17T15:33:29.000061Z

cool, i'd like to try it out sometime

justinlee 2018-01-17T16:14:26.000463Z

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

justinlee 2018-01-17T16:15:23.000036Z

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

2018-01-17T16:15:47.001016Z

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

2018-01-17T16:16:13.000108Z

though you can work around this by using derived-atom

2018-01-17T16:16:38.000279Z

also i find myself passing around multiple cursors to a component

rauh 2018-01-17T16:17:19.000940Z

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

2018-01-17T16:18:04.000122Z

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

justinlee 2018-01-17T16:18:52.000577Z

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

rauh 2018-01-17T16:19:18.000999Z

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.

rauh 2018-01-17T16:20:33.000554Z

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)

2018-01-17T16:21:18.000649Z

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

rauh 2018-01-17T16:21:51.000805Z

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

justinlee 2018-01-17T16:22:29.000689Z

oh got it

justinlee 2018-01-17T16:24:29.000049Z

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.

justinlee 2018-01-17T16:24:59.000219Z

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

justinlee 2018-01-17T16:25:09.000354Z

But I totally see the points you guys are making.

rauh 2018-01-17T16:25:36.001077Z

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)

justinlee 2018-01-17T16:27:01.000245Z

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.

rauh 2018-01-17T16:28:52.000088Z

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.

justinlee 2018-01-17T16:29:21.000840Z

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

justinlee 2018-01-17T16:30:17.001004Z

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

rauh 2018-01-17T16:31:01.000250Z

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.

justinlee 2018-01-17T16:31:47.000357Z

ooh that’s nice

justinlee 2018-01-17T16:34:43.000047Z

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?

rauh 2018-01-17T16:36:42.000380Z

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

2018-01-17T16:49:20.000173Z

@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

2018-01-17T16:49:55.000707Z

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

martinklepsch 2018-01-17T21:06:28.000071Z

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