re-frame

https://github.com/Day8/re-frame/blob/master/docs/README.md https://github.com/Day8/re-frame/blob/master/docs/External-Resources.md
lucian303 2021-03-10T00:21:32.153700Z

in a reg-event-* fn, if i need a value from the db, is it better practice to subscribe to it or access it directly from the db co-fx?

p-himik 2021-03-10T00:43:44.153800Z

Use subscribe only in views and in signal functions of other subscriptions (maybe also in sub bodies and in reg-sub-raw). Don't use it in event handlers. So yes, just access the right value in the cofx map.

lucian303 2021-03-10T01:22:28.154Z

gotcha thanks

lucian303 2021-03-10T01:50:47.155900Z

when i'm using the db and another source for my subscription, is it normal that i provide a subscription to the entire db myself? the db param to reg-sub doesn't seem to be provided if i'm providing a subscription to derive the value from. for example, is this typical?

(rf/reg-sub
  :db
  (fn [db _]
    db))

(rf/reg-sub
  :some-id
  :<- [:db]
  :<- [:kee-frame/route]
  (fn [[db route]]

2021-03-10T02:07:03.156500Z

@lucian303 You'll want to understand the difference between Layer 2 and Layer 3 subscriptions http://day8.github.io/re-frame/subscriptions/

lucian303 2021-03-12T20:58:05.208700Z

thanks @mikethompson i see why that was a bad idea and it was easily fixable

2021-03-10T02:08:14.157Z

See them in action, with further explanation, here within the todomvc example: https://github.com/day8/re-frame/blob/master/examples/todomvc/src/todomvc/subs.cljs

pinealan 2021-03-10T14:23:05.159400Z

are there any example apps/guides that sets up websockets in a re-frame app?

p-himik 2021-03-10T14:24:42.159500Z

I don't know of any examples but I use it as any other effect, although in this case it is stateful. I'm using Sente and I have two effects - one to create the connection and one to send messages. That's it. I don't think there should be anything more to it.

pinealan 2021-03-10T14:28:04.159700Z

that make sense, I was already guessing that messages should be events/effects, but didn’t think of treating connection management as such too, thanks for the suggestion

mokr 2021-03-10T16:37:02.173300Z

Hi, just curious, is anyone using subscriptions as input to events? Eg. via the inject cofx provided by https://github.com/den1k/re-frame-utils that is referred to in https://github.com/day8/re-frame/issues/255. The reason I ask, is the I very often end up in the situation where I have some derived and usually heavily processed data available in a subscription, but need it in an event as well. In general I feel that it would be much cleaner to not have to work around it by re-processing, write derived data back to db or route it via UI code. I believe it would also enable me to minimize the number of locations that knows about where in DB a given piece of source data lives. PS: In relation to issue 255 my usecase is bullet 1), using data in a subscription, not triggering an event when sub data changes. I would also like to use subscriptions that is not in use by UI code, but might well be “sibling” nodes in the subscription graph. I’m aware that there is a performance penalty there, but I kind of assume that would be ok from a usability point-of-view for less frequent events. Thought I’d just ask before I start experimenting with a 4 year old add-on…

p-himik 2021-03-10T16:38:26.173600Z

This question gets asked once or twice a month, so yeah, there are people that do that. :)

mokr 2021-03-10T16:40:40.173800Z

OK, thanks. If we assume that they don’t just ask the question, then hopefully some see this and can share some experiences 🙂

2021-03-10T16:49:15.174100Z

We are using the pattern in a couple of places as well, and while it seems easy to reuse subscriptions as data extractors outside of "view" code, I also think that depending on subscriptions requires understanding the context in which that code runs. Basically whatever depends on a subscription is no longer a pure code and thus all common consequences.

2021-03-10T16:50:42.174300Z

We tend to reuse pure function between handlers and subscriptions instead.

p-himik 2021-03-10T16:51:29.174500Z

Event handlers can be pure - the aforementioned re-frame-utils just injects a cofx. You don't subscribe anywhere explicitly.

2021-03-10T16:52:07.174700Z

It's also super tempting to reuse a cached value from a subscription instead of calculating one from scratch, especially when calculation happens frequently.

2021-03-10T16:52:49.174900Z

To me this topic still remains an unanswered question in re-frame

mokr 2021-03-10T16:52:59.175100Z

Thanks, @roman01la I see what you mean. While the handler can still be pure, as @p-himik says, the overall situation is less “pure”

p-himik 2021-03-10T16:53:08.175300Z

The downside is that if that sub is not used in any view, it will be computed on each event dispatch. A teeny bit slower even, because of the cache and the reaction machinery involved. IIRC there's a flag to leave such a sub in a cache even if it's not used by a view, so at least there's a remedy.

2021-03-10T16:54:26.175600Z

> The downside is that if that sub is not used in any view, it will be computed on each event dispatch We are working around that by maintaining a pool of such subscriptions, so that they don't get GCed

mokr 2021-03-10T16:54:50.175800Z

But what exactly might “slower” mean here? 100ms? 1s?

p-himik 2021-03-10T16:55:12.176Z

@roman01la Why a pool, given that there's a way to do that via re-frame-utils via the :ignore-dispose metadata?

2021-03-10T16:56:02.176200Z

To me, since re-frame is essentially a memoized computation graph it does make sense to use it for generic computations, maybe it's that re-frame's API is tailored towards state management in UIs

2021-03-10T16:56:20.176400Z

Re: performance, this is relevant, I think? https://github.com/day8/re-frame/issues/657

2021-03-10T16:56:28.176700Z

@p-himik I'm not aware of that option, can't really tell why

p-himik 2021-03-10T16:56:39.176900Z

@mokr I've never measured but I'm pretty sure that caching and reagent machinery won't slow your events to a noticeable degree. Otherwise, all your subs would've been slow already. The absence of caching or the absence of GC on the other hand is a real issue where you have to make a conscious decision on what you want more.

2021-03-10T16:57:40.177100Z

It should be noted that unless that issue is fixed, that's an 2^n performance issue if you have derived subs based on derived subs -- it can make a difference.

p-himik 2021-03-10T16:58:14.177400Z

@timothysdean That particular issue should not affect performance. It's just a deref.

mokr 2021-03-10T16:58:38.177600Z

Absence of caching sound ok, but absence of GC? That sound like a leak, I I thought the penalty was partly due to it avoiding leaks?

2021-03-10T16:58:44.177800Z

Absent caching the deref has a cost, right?

p-himik 2021-03-10T16:59:34.178Z

No. re-frame-utils disposes of a sub explicitly. By itself, sub cache is never pruned.

mokr 2021-03-10T17:00:23.178300Z

Today my actual usecase was a situation where the user has filtered down a number of nodes to a selection that should be sent to backend for processing. So, a one-off thing really.

p-himik 2021-03-10T17:01:27.178600Z

In regular re-frame apps, the cache is cleared of a particular sub when that sub is no longer used in any reactive context (a view, as a signal sub, being deref'ed in a reaction). Since event handling happens outside of a reactive context, by themselves any subs there won't be removed from the cache (that's also the reason for why you should never call subscribe in a JS event handler, for example). And that's why re-frame-utils disposes of such subs manually, unless the appropriate metadata is set.

mokr 2021-03-10T17:06:24.178800Z

Are you referring to the :ignore-dispose metadata of re-frame-utils? The way I read it that is only disabling the warning.

p-himik 2021-03-10T17:07:45.179Z

Oh, you're correct! I was wrong about it. Now I see why @roman01la had to have a pool of subs.

mokr 2021-03-10T17:11:10.179200Z

So, all in all if I decide to use this inject, and without a pool, it is safe, but I pay a performance penalty? I’m not messing up re-frame in some other more severe way affecting other part of the app?

p-himik 2021-03-10T17:12:53.179400Z

Right. But you don't "mess up" re-frame in any other way anyway. It's just a tradeoff between performance and having a memory leak (and depending on how that pool is implemented, even the leak can be mitigated).

mokr 2021-03-10T17:15:25.179600Z

Thanks for all the input. With that in mind I think I’ll have a go and see where it takes me.

1👍
2021-03-10T21:50:08.194300Z

I refer to @mokr's question immediately above and to the answers provided by @p-himik and @roman01la... I'd like help from you guys in writing a good problem definition (the best gift you can give yourself when solving a problem is a good problem definition). And that's because (as @p-himik pointed out this come up a bit too often and we need a solution). I'll turn this into an issue. My first cut of a problem definition in note form is: • within a re-frame app ... • ... for a certain period of time (perhaps while a certain panel is showing) ... • ... there's a n need to compute a materialised view of data within app-db ... • ... which will be used both within views (provided by subscriptions) ... • ... and within event handlers. • The computation involved may be a CPU expensive, so we want to cache it. Ie. we don't want to have it calculated via subscriptions and then ALSO calculated within event handlers. We want it only calculated once, when required and as inputs to the calculation change, and then available to both contexts. • BUT we also don't want it calculated outside of the "time" when it is needed. For example, the calculation might only be needed when a single panel is showing to the user. Just to repeat. I'm more interested in a crystal clear problem definition at this point, and less about solutions (although good ideas are welcome).

1👍
2021-03-10T21:58:39.195100Z

Actually, I created an issue to collect information https://github.com/day8/re-frame/issues/680

2021-03-10T22:47:01.195300Z

The problem statement is crystal clear to me, thanks 👍

1➕