Fork me on GitHub
#re-frame
<
2017-11-16
>
danielcompton05:11:25

Big thanks to @mhuebert for his work on this, supporting React 16 and truncating namespaces.

mikethompson04:11:57

^^^ we can spend a bit more time/budget on re-frame-trace so there will be one further release soon (before Christmas) but, in the meantime, we've done this release so people can try it and give feedback .... and, of course, provide PRs for things they'd like to see added. re-frame-trace is pretty usable at this point (although still a work in progress)

mikethompson04:11:32

We'll run out of time/budget soon and have to go back to money-making stuff. So the window for feedback is now. Give it a go.

jeaye04:11:31

Feedback: Please use a dynamic var, not a Closure define, as mentioned here https://github.com/Day8/re-frame-trace/issues/75#issuecomment-343685227

mikethompson05:11:10

@jeaye we have no experience with React Native so this kind of work will have to be delivered via PRs supplied by others.

mikethompson05:11:48

We're open to the idea, but just a bit clueless

jeaye05:11:22

This request is only for a dynamic var for enabling re-frame-trace, rather than a Closure define.

jeaye05:11:38

React Native experience isn't assumed or required. 🙂

mikethompson05:11:28

You'd be amazed at how opaque that was request was :-)

jeaye05:11:48

Yep, I see how I could've worded that much more clearly.

jeaye05:11:54

Sorry about that.

mikethompson05:11:02

We're keen to help

mikethompson05:11:10

But you might have to do the PRs

mikethompson05:11:28

That one would be pretty easy, I'd imagine

mikethompson05:11:38

Or at least create a clear Issue for Daniel

jeaye05:11:57

My assumption is that a Closure define was used to better elide code when tracing is disabled, but it is the one bit of logic that, at this point, is needed to support RN. Do you know of any other reason to prefer a Closure define?

mikethompson05:11:58

I've got a feeling he might not have got your meaning either

jeaye05:11:54

@mikethompson Daniel and I had a good discussion on the meaning, but it looks like I need to clarify further. 1. The ticket was opened as a request for RN support, which Daniel made clear wasn't going to happen on your end (he and I had a VOIP call to discuss what would need to be done); 2. After hacking changes into both re-frame and re-frame-trace, I was able to prototype a solution which works with RN. One key thing that needs to be done, on the re-frame-trace side, is moving away from the Closure define.

jeaye05:11:12

So I bring that up separately here, since it's a bite-sized task that doesn't require RN knowledge.

jeaye05:11:42

I linked to the ticket only because I provided a list there of the things which need to be addressed in order to support this.

mikethompson05:11:18

Does RN need only this one issue solved, or are there many?

jeaye05:11:19

I know the guys over at re-frisk-remote are doing something with it, but I'm not sure what exactly they're up to.

jeaye05:11:15

@mikethompson There are two. One logic, one organization. 1. Dynamic var vs Closure define; 2. The UI code needs to be removed from trace.cljs and put anywhere else.

danielcompton05:11:25

Big thanks to @mhuebert for his work on this, supporting React 16 and truncating namespaces.

jeaye05:11:27

In re-frame, there are two issues as well. 1. js/performance doesn't exist, so it can't be referenced; 2. java.lang.Exception is improperly referenced in a cljc file which is actually compiling for CLJS, just in a macro

danielcompton06:11:29

@jeaye open up some issues for them on the right repositories and we can take a look. Not too keen on getting rid of the closure define, as it helps a lot for DCE, but there might be other ways around it

borkdude16:11:15

Can this be rewritten in a better way?

(reg-sub
 ::last-result?
 (fn [[_ id]]
   (subscribe [::substate id]))
 (fn [substate [_ id query]]
   (get-in substate [:last-result? query]))

danielneal16:11:35

afaik the new thing is - because subscriptions are cached, you can do this

(defn some-ui-thing [id query]
  (let [sub-state @(subscribe [::substate id]            
        last-result @(subscribe [::last-result? id query])]
    [:div (pr-str last-result)])
so you don't need dynamic subscriptions, you can call subscribe every time and reframe will do the right thing

borkdude16:11:03

(updated my question)

danielneal16:11:11

then your sub is

(reg-sub ::substate 
     (fn [[_ id] ...))
 
 (reg-sub ::last-result
   :<- [::substate]
   (fn [substate [_ id query])
     (get-in substate [:last-result? query)))

danielneal16:11:56

unless did I misunderstand the question?

borkdude16:11:25

I think my question is, if you still need the two funs, or can the :<- [::substate] syntax also be used with dynamic values?

danielneal16:11:16

I'm not sure I'm afraid

mikerod17:11:14

@borkdude I’be been writing it that verbose way

mikerod17:11:30

I wasn’t sure if the “caching” thing was the only good reason for having the separate fn’s

mikerod17:11:48

I was wanting to write some sort of helper soon though to make that pattern less clunky.

deg17:11:54

Where is :<- documented? (Googles does not make this search easy... 🙂 )

deg18:11:52

Ah, thanks. Nowhere in the docs directory?

mikerod18:11:17

Hmm not sure on that one

mikethompson20:11:07

Also, in the API docs: https://github.com/Day8/re-frame/blob/master/docs/API.md if you click on reg-sub, you'll get to what @mikerod pointed to

borkdude20:11:36

I have two subscription, but I’m confused why the second receives a subscription and not the result of the subscription:

(reg-sub
 ::subnav-config
 (fn [db [_ page-id]]
   (subscribe [:dre.search.subs/subnav #_(get-in db [page-id :page/subnav-sub])])))

(reg-sub
 ::subnav-visible?
 (fn [[_ page-id]]
   (subscribe [::subnav-config page-id]))
 (fn [config _] ;; config is a subscription here, why?
   (:subnav/visible? @config)))

borkdude20:11:33

(get-in db [page-id :page/subnav-sub]) evaluates to a keyword: :search.subs/subnav

borkdude20:11:53

Maybe (subscribe [::subnav-config page-id])) returns a subscription of a subscription?

borkdude21:11:23

hmm, it doesn’t matter when I replace the expression with a keyword literal

danielcompton21:11:44

@borkdude that's the low level way of chaining subscriptions

borkdude21:11:39

@danielcompton Then why does this work without deref?

(reg-sub
 ::last-result?
 (fn [[_ id query]]
   (subscribe [::substate id]))
 (fn [substate [_ id query]]
   (get-in substate [:last-result? query])))

borkdude21:11:01

Isn’t that the same?

danielcompton21:11:07

sorry, can you explain the question more? Not quite following

borkdude21:11:36

In the latter example ::last-result?, the second function receives the result of the subscription, not the subscription itself

borkdude21:11:46

But in my first example ::subnav-config and subnav-visible?, I have to deref config

danielcompton21:11:33

subscribe returns a Reagent Reaction. If you use a single computation function (which used to be the only way to do this), and call subscribe, you are returned a reaction that you need to dereference.

danielcompton21:11:11

re-frame provides an additional sugared version of reg-sub where you can provide a second "inputs" function. This function does subscriptions and (normally) returns reactions. When your computation function is run, re-frame derefs all of the reactions returned by the inputs function, so you don't need to.

danielcompton21:11:11

In your case, ::subnav-config is returning a reaction, which is then wrapped up in a parent reaction. If you want to do a subscription like that then it should be dereferenced before returning

danielcompton21:11:38

As a general rule of thumb, you shouldn't need to be doing any dereferencing inside a subscriptions computation fn or inputs fn, because re-frame does all of the necessary work for you. You just write functions that take data and return data (or return reactions in the case of an input fn)

borkdude21:11:50

> which is then wrapped up in a parent reaction why?

borkdude21:11:10

normally you would return a plain value and now this value is wrapped in a reaction, like every value

borkdude21:11:41

so I should write:

(reg-sub
 ::subnav-config
 (fn [db [_ page-id]]
   @(subscribe [:dre.search.subs/subnav #_(get-in db [page-id :page/subnav-sub])])))
?

borkdude21:11:37

This also works, but maybe it comes down to the same:

(reg-sub
 ::subnav-config
 (fn [db [_ page-id]]
   (subscribe [:dre.search.subs/subnav #_(get-in db [page-id :page/subnav-sub])]))
 (fn [val [_]]
   val))

borkdude21:11:35

oh it doesn’t work, because when I add the second function, the destructuring of the first function breaks

borkdude21:11:59

I’m not sure if I can get access to the db when I use multiple functions. Can’t see an example here: https://github.com/Day8/re-frame/blob/master/examples/todomvc/src/todomvc/subs.cljs

borkdude21:11:12

So, to rephrase my question, if I use something like this:

(reg-sub ::some-sub
  (fn [...] (subscribe ...))
  (fn [res] (:foo res)))
is there a way I can get the db?

mikerod21:11:42

@borkdude you can have multiple subscriptions

mikerod21:11:46

at the same time so:

mikerod21:11:38

(reg-sub ::some-sub
  (fn [...] [(subscribe [:db-one]) (subscribe ...)])
  (fn [[db res] _] (:foo res)))

mikerod21:11:10

your signal fn can return a vector of multiple subscription “signals”

mikerod21:11:16

you can include a “db” one there

mikerod21:11:31

I don’t typically need the root db though, you may just want a subs accessor on some part of it

mikerod21:11:10

However, in your question I’m a bit confused which of the 2 functions you want the db to passed to

borkdude21:11:46

The first one

mikerod21:11:47

The signal returning fn (don’t know correct term here I don’t think) it takes the same arg vec as the subscription

mikerod21:11:59

So I think you may just want to structure a bit differently

danielcompton21:11:07

Yeah, usually you shouldn't be accessing DB directly

danielcompton21:11:13

except for top level subscriptions

danielcompton21:11:23

as any change to DB will cause everything depending on it to rerun

danielcompton21:11:38

So usually you would have a subscription returning the parts of app-db you want, and then depend on that

borkdude21:11:51

What I’m doing: I have a subnavigation component that can have specific behavior per page. I want to have a subscription per page that this subnavigation component subscribes to.

borkdude21:11:19

This subscription tells the component if it should be visible, etc.

borkdude21:11:39

E.g. “if the number of search results is 0, the subnavigation component should not be visible"

borkdude22:11:25

so I want the visibility to depend on things, instead of setting it manually

borkdude22:11:43

and these “things” are different per page

borkdude22:11:49

hence a subscription per page