Fork me on GitHub
#re-frame
<
2018-04-04
>
caleb.macdonaldblack00:04:19

So I have some view code (A table) that creates a new row whenever the last row has a value in any of its cells. It will also delete any row where all cells are empty. I plan on reusing this table. I’m tossing up whether or not to build this row creation & removal logic into events & subs or functions in view code. If I do events & subs, should I dynamically register many with some sort of unique key on component creation? or register once for all components and pass in a unique key when subscribing or dispatching?

caleb.macdonaldblack00:04:12

Also what are your thoughts on storing local state for a view component in the on-create lifecycle method (of a form 2 component). Why would you choose local state over app db and vice-versa?

tomaas07:04:06

Hi, in reg-event-fx there are :db, :http-xhrio, :dispatch. If I want to do some side effects like prn is there any to key to use or do I have to create one?

caleb.macdonaldblack07:04:50

@tomaas idk if I would consider logging to be enough of a side effect to make a seperate fx handler for it. I would just log in the event handle. But yeah as far as I know there is no logging fx. You would need to create it.

tomaas07:04:45

ok thanks. Actually I want to preload images in src attribute

tomaas07:04:24

so i was looking for some handler which in general does some side effect work silently that nobody cares of (does not need to dispatch anything once it completes)

tomaas07:04:42

i've created a custom one

mikethompson08:04:00

Standby for a new release of re-frame-10x. Final touches being added. Not long. Maybe one more sleep.

mikethompson10:04:07

I'm stealing Daniel's thunder but ... a teaser ...

mikethompson10:04:53

Did a screenshot appear here ^^^ for everyone. I'm getting a message about not enough space.

kurt-o-sys10:04:23

I'm using re-frame, but I'm having problems with subscriptions: in my app, it seems some of the subscription handlers are not registered when I'm using them... I don't understand why that would be the case.

manuel10:04:59

@mikethompson yes, it's there 🙂

mikethompson10:04:57

You are probably missing the necessary requires to actually pull in the namespaces

kurt-o-sys10:04:21

in one my nss, I have somthing like this:

(def inject-now (partial generate-fn (re-frame/subscribe [:now])))

kurt-o-sys10:04:26

oh, ok... let me try 🙂

kurt-o-sys10:04:51

so, basically, it's not enough to add the re-frame.core namespace and do re-frame/subscribe to add the subs, right?

kurt-o-sys11:04:45

ok, trying again (conceptually, this is what I have): my.subs:

(ns my.subs
  (:require [re-frame.core :as re-frame]
            [my.db :as db]
            [my.model :as m]))

(re-frame/reg-sub
 :now
 (fn [db]
   (get-in db [::m/view :now])))
my.db:
(ns my.db
  (:require [my.model :as m]
            [cljs-time.core :as time]))

(def default-db
   ::m/view     {:now (time/date-time 2018 1 3)})
my-ns:
(ns my-ns
  (:require [re-frame.core :as re-frame]
            [my.subs]))

(defn inject-now [c]
  (c {:now @(re-frame/subscribe [:now]) }))
accessing parameter :now in component c gives me nil. I expect a date... What am I missing?

mikethompson11:04:15

Have you done an :initialize-db kinda event?

mikethompson11:04:26

To actually put a value into app-db

mikethompson11:04:46

See the two examples in the repo

kurt-o-sys11:04:58

yeah... that's there.

kurt-o-sys11:04:24

(defn init! []
  (re-frame/dispatch-sync [:initialize-db])
 

kurt-o-sys11:04:31

in core.cljs

kurt-o-sys11:04:57

the weird thing is, it did work before I added the function inject-now

kurt-o-sys11:04:23

(but I'm refactoring a bit, and I don't get why subscriptions wouldn't work at that point)

mikethompson11:04:41

Seems wierd ....

(def default-db
   ::m/view     {:now (time/date-time 2018 1 3)})

kurt-o-sys11:04:51

what's weird?

mikethompson11:04:05

It isn't valid clojure

kurt-o-sys11:04:08

oh, forgot a { :

mikethompson11:04:28

I notice you are using ::m/view in different namespaces

kurt-o-sys11:04:33

(def default-db 
  { 
     ::m/view {now ....}})

mikethompson11:04:34

They won't be the same thing

mikethompson11:04:00

That's why you are getting nil

kurt-o-sys11:04:02

right... I know, but that part seems to work, sec... it's a bit weirder (imo)

mikethompson11:04:18

Absolutely won;t work .... given what i can see

kurt-o-sys11:04:18

no, it does work with these namespaced keywords.

kurt-o-sys11:04:31

I did work...

kurt-o-sys11:04:43

it's that function that makes things not work 😛

kurt-o-sys11:04:47

Let's see this:

mikethompson11:04:16

Chnage from ::m/view everywhere to :m/view

mikethompson11:04:36

As presented, your code can't wark. i promise

kurt-o-sys11:04:43

please no, it does work with ::m/view. That's not the problem. It's something else

kurt-o-sys11:04:02

It did, please listen... these namespace keywords did work.

kurt-o-sys11:04:07

honestly 😛

kurt-o-sys11:04:34

When I add (println @(re-frame/subscribe [:now])) to my namespace give a value when I start the app

kurt-o-sys11:04:20

but that value is suddenly removed when loading the page (after login of the app). Will dive deeper into it.

kurt-o-sys11:04:37

(so, to say, that subscribe initially works, but for some reason, the value is set to nil)

mikethompson11:04:39

I can only work with the code you have given. And it absolutely 100% won;t work because ::m/view will resolve to different keywords in different namespaces. And that perfectly explainsthe nil you are seeing.

mikethompson11:04:15

You asked for help. You provided code. That's the problem.

kurt-o-sys11:04:20

it can work, check it clearly:

kurt-o-sys11:04:27

I use that ::m/view in my db

kurt-o-sys11:04:44

and in my subs, I load that same namespace

kurt-o-sys11:04:09

using (get-in db [::m/view ...])

mikethompson11:04:19

Can I suggest you try using re-frisk or re-frame-10x to look inside of app-db

kurt-o-sys11:04:21

so it's pointing to the same ns 🙂

kurt-o-sys11:04:59

doesn't work, since I'm using npm (react) libs and I have to add them using http://blob.tomerweller.com/reagent-import-react-components-from-npm

kurt-o-sys11:04:12

which makes 10x not usable, unfortunately.

kurt-o-sys11:04:34

(I tried adding npms another way, didn't work - that's the only thing that worked so far)

mikethompson11:04:30

(re-frame/reg-sub
 :now
 (fn [db]
   (println  ::m/view)     ;; <----- 
   (println db)          ;; <----
   (get-in db [::m/view :now])))

kurt-o-sys11:04:30

so, (println @(re-frame/subscribe [:now])) this works in my ns itself (not in a function)

kurt-o-sys11:04:50

in the function, it gives nil

mikethompson11:04:50

I'm assuming you are using clj-devtools

kurt-o-sys11:04:52

just using the chrome dev console.

danielcompton11:04:00

@kurt-o-sys bridging the gap here, can you show the ns form of one of the files that uses the ::m keywords?

kurt-o-sys11:04:22

yes, see above, sec.

kurt-o-sys11:04:04

(ns my.db
  (:require [cljs-time.core :as time]
            [my.model :as m]))

kurt-o-sys11:04:30

(println @(re-frame/subscribe [:now]))

(def inject-now (partial inject-fn @(re-frame/subscribe [:now])))

kurt-o-sys11:04:55

on the println, it gives a value, using the inject-now, it gives nil

kurt-o-sys11:04:50

(I have a helper function to inject subscriptions in components - similar to reacts hoc.

kurt-o-sys11:04:30

(something must be go wrong there... oh, maybe it's about when things are evaluated and availability of subs)

mikethompson11:04:15

partial will lock in an initial value of the subscription?

danielcompton11:04:43

Have you explained further up thread what you're actually trying to do here?

kurt-o-sys11:04:55

yeah, sorry, I didn't. What I want to do is make a kind of 'injector for re-frame subscriptions', the same way one uses hocs with react, so for example, with react components injecting queries for the database (apollo - doesn't really matter)

(-> my-component
    reagent/reactify-component
    ((query/all-services-hoc))
    ... 

kurt-o-sys11:04:38

So, I'd like to do something like this:

(-> my-component
    ((re-frame/inject-now-subscription))
    ...

kurt-o-sys11:04:23

that inject-fn works fine for re-frame/dispatch, having problems with re-frame/subscribe. But I'm getting closer, with that 'lock-in of the initial value'.

danielcompton11:04:02

Yeah, I don't think you want to be derefing it in the initial load

danielcompton11:04:25

You need to inject the reaction and only deref it once you're inside the rendering of the component

danielcompton11:04:38

Failing to do this will lead to all manner of strange bugs, like the ones you described 🙂

kurt-o-sys11:04:57

that may solve the problem, let me check....

kurt-o-sys11:04:15

still need to solve the specs of the original component... all 'subscribe'-specs are Reaction, not date anymore...

danielcompton11:04:44

Yeah that's a thorny one, I've dealt with the same thing with core.async and Manifold deferreds

danielcompton11:04:57

Not sure if there are any great solutions at the moment

kurt-o-sys11:04:09

oh, I was about to ask 🙂

danielcompton11:04:24

I guess you could do a spec that peeked at the Reaction's value, but that would be pretty dirty

danielcompton11:04:37

and might be buggy

kurt-o-sys11:04:58

another solution is to compose into another function/component with the deferred vals?

danielcompton11:04:42

Reagent's change tracking relies on you deferring values in a render function, so it knows when to re-render

danielcompton11:04:54

as long as your derefs are happening then, you should be ok

danielcompton11:04:05

You could also try and spec the value as it is produced by the subscription

kurt-o-sys11:04:58

right. or just keep deferring inside the function/component itself. Specs will be less clear, but well...

mikethompson11:04:06

@kurt-o-sys sorry I was wrong before and a little terse. I'm currently knee deep in powerpoint and not enjoying it. Grumpy.

kurt-o-sys11:04:33

np... thanks a lot for your help! just having to explain it to (grumpy) people may help a lot 🙂

kurt-o-sys11:04:04

quicky: is there a spec for a re-frame Reaction.

mikethompson11:04:56

I doubt it. Its a deftype internal to reagent

mikethompson12:04:41

Easier to spec the contents which will be a value

kurt-o-sys12:04:57

going for inner components, and spec'ing these. makes more sense, and looks less hacky.

leontalbot18:04:12

Is the following legit in re-frame?

leontalbot18:04:22

(ns app.effects.modal
  (:require
   [re-frame.core :as rf]))

(defn remove-back-scroll! []
  (-> js/document .-body .-classList (.add "modal-background-no-scroll")))

(defn set-back-scroll! []
  (-> js/document .-body .-classList (.remove "modal-background-no-scroll")))

(rf/reg-event-db
 :modal/active
 ;; Takes a modal id to be opened
 ;; Can also take an optional path to get modal id
 (fn [db [_ id & [path]]]
   (if id (remove-back-scroll!) (set-back-scroll!))
   (assoc-in db (or path [:modal/active]) id)))

leontalbot18:04:59

I feel like the way I introduce the following side-effects isn’t idiomatic

leontalbot18:04:03

(if id (remove-back-scroll!) (set-back-scroll!))

leontalbot18:04:24

Thanks in advance!

mikerod19:04:33

@leontalbot for side-effects, you probably want to read a bit on the event handler vs effect handler distinction in the docs

leontalbot19:04:35

(rf/reg-event-fx 
 :modal/handle-back-scroll
 (fn [_ [_ id]]
   (if id (remove-back-scroll!) (set-back-scroll!))))

(rf/reg-event-fx 
 :modal/active
 (fn [fx [_ id & [path]]]
   {:db       (assoc-in (:db fx) (or path [:modal/active]) id)
    :dispatch [:modal/handle-back-scroll id]}))

leontalbot19:04:53

@mikerod Thanks. Is that better? ^

danielcompton19:04:29

@mikerod more like {:db ... :back-scroll :remove} or {:db ... :back-scroll :set}

danielcompton19:04:00

Setting the back scroll is a side effect, so it should go into an effect handler

mikerod19:04:07

@danielcompton I believe you meant to tag @leontalbot in that one

leontalbot19:04:53

@danielcompton Thanks a lot! Would you mind sharing a bit more so I understand how to integrate this?

danielcompton20:04:50

Take a look at the docs on effects, that’s a good place to start