Fork me on GitHub
#re-frame
<
2021-04-20
>
paulbutcher14:04:19

I feel that this is probably a FAQ, but I haven’t been able to scare up an answer. Is there some way to “weakly subscribe” to something in the database? I.e. I want access to the value within my component, but I don’t want my component to update when the value changes. Is this possible?

p-himik14:04:40

Using a form-2 Reagent component should help.

p-himik14:04:23

Or reagent.core/with-let with @ being inside its bindings form.

paulbutcher14:04:48

I think I see what you’re suggesting. If I understand, that will allow me to access the value as it was when the component was created. I’m interested in whatever the value happens to be right now. Let me try to explain: I have :x, :y, and :z in the app-db. I want my component to update whenever :x or :y change, but when it updates, take whatever the current value of :z is into account. If I subscribe to :z, it will also update whenever :z changes. Perhaps I can do that with a form-2 component, but I’m not sure I can immediately see how?

p-himik14:04:53

I see. Well, a proper re-frame friendly approach would be to have an extra key, something like :z-for-x-y, that would be set to the value of :z only when :x or :y is changed. And you would just subscribe to the value of :z-for-x-y - no magic whatsoever. If you don't have a small known set of events that update :x and :y where you could put the code updating :z-for-x-y, you can use a global interceptor for it.

paulbutcher14:04:41

Ah, got you. Thanks. Perhaps I should explain what I’m trying to do in more detail - there may be a completely different way to solve the problem: I’m writing a component which wraps a large pre-existing Javascript component (https://vega.github.io/vega/). I’m doing this by having a component like this:

(defn vega-view []
  (let [data @(re-frame/subscribe [:vega-data])]
    [:div {:ref #(create-view % data)}]))
The create-view function creates the Vega view, and everything’s good. Except… Vega is full of its own state that I need to occasionally interact with. In particular if my component repaints (because data has changed) I want to read the values out of the Vega component, create a new Vega component, then put the values back. Currently I do this by having a clojure.core/atom that I store the Vega view in, which I refer to within create-view. I’d like to put it in app-db however because other components elsewhere within the app also need access (and will need to refresh if it changes). Perhaps I’m pushing re-frame in a direction it doesn’t want to go here though.

p-himik14:04:52

Just use https://github.com/vega/react-vega. ;) It deals with all that.

p-himik14:04:22

And use it via regular Reagent/React interop - works like a charm for me.

paulbutcher14:04:26

Ah! Good luck to find someone else doing something very similar! I did try to use react-vega back when I started down this road, and got into a real mess. Perhaps I should revisit. I’m not sure that it could solve the problem that I’m trying to solve though? I’m programmatically generating my Vega spec (because the spec changes depending on the specifics of the data being visualised) and want to save the values of certain signals from the previous instance of Vega and copy them into the new one.

p-himik14:04:31

I also generate the spec depending on the data. But I've never tried preserving signal values.

paulbutcher14:04:45

No worries. I think you’ve answered my main question which is that my initial thought about how to use re-frame won’t fly (for which many thanks). I can certainly find a way to make it work, it’ll just be a bit messy (which is fine - the interface between a nice functional re-frame app and a very imperative Vega component will always get a bit messy at the join…)

paulbutcher14:04:09

I’m curious now - what are you visualising?

p-himik15:04:37

I'm working together with the Utrecht University on a platform that would allow users to select the right breeding partners for their dogs, so all the breeding regulations are followed - to avoid any diseased offspring. The platform itself is not public yet, but here are a couple of charts from the work in progress: file:///home/p-himik/Pictures/screenshots/Screenshot_20210420_175902.png

paulbutcher15:04:40

Very nice! 👍

valtteri17:04:33

You can also check this out. I’ve been using this strategy to wrap OpenLayers, which is highly stateful and imperative. https://github.com/day8/re-frame/blob/master/docs/Using-Stateful-JS-Components.md

valtteri17:04:01

Warning: it’s not fun but it works. 🙂

kennytilton23:04:25

So I am pitching in on a re-frame project and cannot figure out what version of re-frame is being used. The shadow-cljs.edn pulls in only [day8.re-frame/re-frame-10x "0.6.0"]. I cannot find any other "re-frame" linkage. They also use NPM, but npm list shows only react stuff. Damn I miss project.clj. 🙂 Anyone have any idea how to find out what version they are using. Their timezone is unconscious right now or I would ask them. Thx! 🙏

kennytilton23:04:51

Ah, found a re-frame-1.1.2 jar under shadow-cljs. Bingo.

superstructor00:04:58

You probably want to upgrade 10x as that version is not officially compatible, assuming they are using a version of reagent/react equally as new as re-frame 1.1.2; ref https://github.com/day8/re-frame-10x#compatibility-matrix

kennytilton05:04:09

Thx, yeah, I saw that low version on 10x. tbh, I never wrapped my head around 10x as a debugging tool. But worth doing anyway as long as we have the beast in there. 🤷 New around here, do not want to make waves. 🌊