Fork me on GitHub
#re-frame
<
2016-12-03
>
cmal04:12:34

Hi, I have just started to use re-frame and there is some problem. I'm encountering re-frame: overwriting :event handler for: :initialize-db and some similar warnings. And then (...core.cljs, ... events.cljs) Figwheel: NOT loading these files. What is the problem? Is there any error with my project settings or something else? thanks.

cmal04:12:29

when I try to trigger the events, I got some error: Uncaught Error: nth not supported on this type function Number() { [native code] } ... ... at events.cljs:21

mikethompson04:12:03

The overwrite warnings is not a problem. Figwheel is reloading a file, and when it does, the registrations are occurring again. re-frame is warning you in case that's a problem.

cmal04:12:03

Here is the relative code :

cmal04:12:23

(ns data-nav-reframe.events
    (:require [re-frame.core :refer [reg-event-db]]
              [data-nav-reframe.db :as db]
              [dirac.runtime])
    (:require-macros [data-nav-reframe.core :refer [log]]))

(dirac.runtime/install!)

(reg-event-db
 :initialize-db
 (fn  [_ _]
   db/default-db))

(reg-event-db
 :set-active-panel
 (fn [db [_ active-panel]]
   (assoc db :active-panel active-panel)))

(reg-event-db
 :left-bar-select
 (fn [db [_ [index]]]
   (log db)
   (log index)
   (assoc db :left-bar-active index)))

mikethompson04:12:07

I'm guessing that last one should be: (fn [db [_ index]] and not (fn [db [_ [index]]]

cmal04:12:06

@mikethompson thanks, I'll try that

mikethompson04:12:21

The overwrite warnings is not a problem. Figwheel is reloading a file, and when it does, the registrations are occurring again. re-frame is warning you in case that's a problem (which it isn't)

cmal04:12:15

@mikethompson that is the problem. Thank you!

cmal04:12:33

👍❤️

andre07:12:14

@shaun-mahood great talk, I am glad that re-frisk did not disappoint 🙂

andre09:12:36

{:http-xhrio {  :on-success      [:good-post-result :good-post-result2]}}
сan i provide vector of post-result events?

andre09:12:28

or only one post-result and additional params?

mikethompson09:12:06

only one event

andre09:12:58

:handler (partial ajax-xhrio-handler
                          #(dispatch (conj on-success %))

andre09:12:44

i need one post-result-fx with :dispatch [:good-post-result :good-post-result2]

andre09:12:56

it's better way yes

andre09:12:54

in @shaun-mahood talk he said you can stop propagation on coeffects, so, for ex. i have coeff for getting value from local storage and if there is no value i want to do not continue

andre09:12:10

i can't found info in docs

andre09:12:42

is it better to stop in coeff, or pass nil and check in the event function?

andre09:12:14

(assoc-in [:coeffect :queue] [])

andre09:12:23

is it legal? 🙂

cmal09:12:39

Hi, is this :let in for loop right? I found the value of selected? did not get a valid value. I did not find such a pattern in the todomvc demo of re-frame. Just want to do (let [...] (fn [] ...)) in a for loop.

(defn left-bar []
  (fn []
    [re-com/v-box
     :children (for [index (range (count icons))
                     :let [name (:id (nth icons index))
                           selected? (subscribe [:selected? index])]]
                 ^{:key index}
                 [re-com/box
                  :size "80px"
                  :child [re-com/md-icon-button
                          :md-icon-name name
                          :size :larger
                          :on-click #(dispatch [:left-bar-select index])
                          :style (left-bar-btn-style index selected?)]
                  ])
     ]
))

mikethompson10:12:11

@andre interceptors fns (:before and :after) are passed a context which is this: https://github.com/Day8/re-frame/blob/master/docs/Interceptors.md#what-is-context

mikethompson10:12:57

Your :before and :after can modify :queue and :stack within the context

mikethompson10:12:25

In that way they can change the event handling process

mikethompson10:12:46

Of course, they are normally changing :coeffects or :effects

mikethompson10:12:13

BUT in advanced cases they can change the entire pipeline via :queue and :stack

mikethompson10:12:20

So if a :before interceptor fn wanted to ADD further interceptors it would add them to the :queue

mikethompson10:12:20

On the other hand, if it wanted to abort the process, it would clear out the :queue and :stack

mikethompson10:12:24

@cmal should you have used @selected?

mikethompson10:12:30

or maybe just do selected? @(subscribe [:selected? index]) note the @

cmal10:12:38

Thanks. I think I make a mistake here.

mikethompson10:12:28

You don't need that fn inside the defn

cmal10:12:45

@mikethompson thanks. I found all the v-boxes were re-rendered each time I click the button, so I moved the subscribe to the outside of the v-box. but this time left-bar-btn-style re-computation was not triggered when I click the button. but the app-db does changed , and reg-sub does run.

cmal10:12:51

(defn left-bar []
  (let [selected (subscribe [:left-bar-selected])]
    (fn []
      [re-com/v-box
       :children (for [index (range (count icons))
                       :let [name (:id (nth icons index))
                             selected? (= @selected index)]]
                   ^{:key index}
                   [re-com/box
                    :size "80px"
                    :child [re-com/md-icon-button
                            :md-icon-name name
                            :size :larger
                            :on-click #(dispatch [:left-bar-select index])
                            :style (left-bar-btn-style index selected?)]
                    ])
       ]
      )))

andre10:12:06

@mikethompson thank you for such a detailed response, but event function will be called anyway, you can just clear interceptors queue?

cmal10:12:12

Sorry to bother. I've made a mistake in the reg-sub. This time it works perfectly. Thanks for you today. You really helped me alot

mikethompson10:12:24

@andre the event handler function is wrapped in an interceptor, on the end of the queue.

mikethompson10:12:52

So if the queue is cleared, so too is the event handler

andre10:12:00

that's it! understand

andre10:12:08

thank you

andre10:12:05

sorry, last question, can i clear queue in the injected coeff?

mikethompson10:12:24

Not sure that you mean

andre10:12:07

(reg-cofx               ;; new registration function
   :local-store 
   (fn [coeffects local-store-key]
      (assoc coeffects 
             :local-store
             (js->clj (.getItem js/localStorage local-store-key)))))

andre10:12:24

if there is no value in the ls . i want to clear queue

andre10:12:29

can i return (assoc coeffect :queue []) ?

mikethompson10:12:18

Ahh. Some misunderstanding here. Remember: 1. these cofx handler are done as a last step by the :after of the last Interceptor in the queue 2. cofx handler are not Interceptors 3. So they dod not have the option of abandoning the process. 4. There is no guarantee about the order in which cofx get called

mikethompson10:12:57

I'm editting the above

andre10:12:18

yes. i need to dig more, thank you, i want to make infographics to understand clear how it works

mikethompson10:12:39

That would be good !!

andre11:12:17

and i thinking now, i'm naming my events using suffix, f.e. :get-data-fx , or :update-value-db, it's clear to read, and i want to color events in re-frisk by this suffix, it should be easy to find pure or effectfull events in the list

andre11:12:22

-db - changing only db -fx - only effect -db-fx - changing db and effect

colin.yates11:12:39

quick Q - does [a-multimethod] where the multi-method resolves to my-cmp change any lifecycle things compared to [my-cmp]. Are they essentially interchangeable? I mean specifically in the sense that (my-cmp) is very different to [my-cmp]. This is for a very optimised (in terms of re-rendering) table with a high number of rows.

colin.yates11:12:39

I assume not. My assumption is that the multimethod resolution is at a lower level than reagent, but you know what happens when you ass-u-me 🙂

colin.yates11:12:11

(and huge congrats to @mikethompson, @danielcompton and the team) - re-frame is coming on leaps an bounds. The simplicity of the interceptors/`coeffects handlers` is sublime. Like all great abstractions it initially receives a ‘huh?’ followed moments later by the lightbulb moment 🙂.)

colin.yates11:12:09

(and if that butter leads you to answer my question above then all the better ;-))

mikethompson11:12:01

@colin.yates I'm not aware of multimethods changing lifecycle related behaviour

mikethompson11:12:28

But I am a bit suspicious of using multimethods around Reagent

colin.yates11:12:23

ok, that’s fine - I think I will steer clear then. The lein template (https://github.com/Day8/re-frame-template) does include them as a way of rendering the current panel though.

mikethompson11:12:44

I thought we'd removed that

colin.yates11:12:58

I generated it last night and it produced:

colin.yates11:12:18

;; home

(defn home-panel []
  (let [name (re-frame/subscribe [:name])]
    (fn []
      [:div (str "Hello from " @name ". This is the Home Page.")
       [:div [:a {:href "#/about"} "go to About Page"]]])))


;; about

(defn about-panel []
  (fn []
    [:div "This is the About Page."
     [:div [:a {:href "#/"} "go to Home Page"]]]))


;; main

(defmulti panels identity)
(defmethod panels :home-panel [] [home-panel])
(defmethod panels :about-panel [] [about-panel])
(defmethod panels :default [] [:div])

(defn show-panel
  [panel-name]
  [panels panel-name])

(defn main-panel []
  (let [active-panel (re-frame/subscribe [:active-panel])]
    (fn []
      [show-panel @active-panel])))

colin.yates11:12:25

this was a result of lein new re-frame pj-rf +test +routes +devcards

mikethompson11:12:17

We should remove that use.

colin.yates11:12:55

would a PR with a simple case be sufficient?

mikethompson11:12:06

Would be great.

colin.yates11:12:30

Oooh, my first lein template journey - I will send it over later today then.

skjutare12:12:14

Are there any re-frame components with custom rendering? I’m not using bootstrap so re-com isn't a good match for me. For me it would be ideal to have something similar to re-com but with a possibility to provide custom rendering. I.e. separate the logic from the hiccup. Is there something like this out there?

mikethompson12:12:37

Not that I've seen

mikethompson12:12:23

I'd be tempted to fork re-com and make it render the way you want it.

mikethompson12:12:40

There's just so many possible needs

skjutare12:12:51

Was just thinking that would be a good idea.

colin.yates12:12:06

@mikethompson https://github.com/Day8/re-frame-template/pull/40 is all yours. Comments appreciated which I will action after lunch.

mikethompson12:12:54

Thanks! Have commented, but will leave it to Matthew to merge

mccraigmccraig13:12:59

multimethods are fine for form-1 components aren't they @mikethompson ? which covers a lot of ground now that form-1s can reasonably subscribe...

cmal14:12:27

Hi, I found the reagent and re-frame todomvc both have some :keys for todo-item, but I dont know what the keys means. I've write the following code but the compiler keep warning me that Every element in a seq should have a unique key. Where is the problem? Thanks!

(defn show-panel-child [id text]
  [:div.show-panel-child
   [:div.child-text
    text]
   [:div.child-delete
    [re-com/md-icon-button
     :md-icon-name "zmdi-delete"
     :size :smaller
     :on-click #(dispatch [:delete-show-panel-child id])
    ]]]
  )

(defn show-panel []
  [:div.show-panel
   (let [children @(subscribe [:show-panel-child])]
     (for [child children
           :let [id (:id child)
                 text (:text child)
                 div (show-panel-child id text)]]
       ^{:key id}
       [re-com/box
        :child div
        :style {
                :background-color "white"
                :margin-bottom "10px"
                }])
     )])

cmal14:12:44

the code of todo-item in todomvc demo is as follows:

(defn todo-item
  []
  (let [editing (reagent/atom false)]
    (fn [{:keys [id done title]}]   ;;; <=== this :keys
      [:li {:class (str (when done "completed ")
                        (when @editing "editing"))}
        [:div.view
          [:input.toggle
            {:type "checkbox"
             :checked done
             :on-change #(dispatch [:toggle-done id])}]
          [:label
            {:on-double-click #(reset! editing true)}
            title]
          [:button.destroy
            {:on-click #(dispatch [:delete-todo id])}]]
        (when @editing
          [todo-input
            {:class "edit"
             :title title
             :on-save #(dispatch [:save id %])
             :on-stop #(reset! editing false)}])])))

colin.yates14:12:48

@cmal are you sure id is not nil? Also, calling (show-panel-child id text) would be more performant as [show-panel-child id text] at which point you might want to rename it to panel-child 😉. Try adding (.log js/console (clj->js children)) between the for and the let.

colin.yates14:12:11

@cmal, ah, I think you are also confusing the use of :keys when destructuring in Clojure and also React’s requirement/wish that every child in a dynamic sequence has a unique key. For reagent (the Clojure binding to React), you can provide the key either as meta-data or as a :key in the props map. So ^{:key id} [comp…] is equivalent to [comp {:key id} …] (1/2)

colin.yates14:12:57

@cmal - the :keys in the todo example have nothing to do with React or reagent, but is simply a convenience Clojure provides called destructuring. If I have a map m of {:a 1 :b 2 :c 3} then if I want to interrogate that map I can do either (:a m) or {:keys [a]} which creates a local var called a and assigns it the value of (:a m). (2/2)

sandbags15:12:51

Yes I am keen to know if multimethods/form-1 has lurking problems since I have just re-written to use that and it seems to work and provides an elegant solution over the use of case etc...

sandbags15:12:15

in a complex app the use of case to select among view components surely has to be a horrible choice

shaun-mahood15:12:32

@andre: re-frisk worked great, without it I couldn't have done the talk the way I wanted - thanks for all your work on it!

gadfly36116:12:12

@colin.yates @mikethompson Will accept and deploy to clojars when im back at a computer, thanks for the PR! :)

shaun-mahood18:12:20

I published a cleaned up and properly working version of the code I used for my re-frame talk at the Conj https://github.com/smahood/re-frame-conj-2016

andre18:12:50

what was the problem, why broken slide doesn't work?

mikethompson18:12:16

@andre that looks accurate

andre18:12:57

@mikethompson this is a draft, i posted it for the review, i'll try to make it more intuitive and straight 🙂

mikethompson18:12:05

It is a hard thing to show because there is time involved

andre18:12:35

i re-read your answer, i was talking about red function on the picture, why did you say 1. these cofx handler are done as a last step by the :after of the last Interceptor in the queue 4. There is no guarantee about the order in which cofx get called

mikethompson18:12:27

Sorry, i got confused there. I was writing cofx but was thinking fx

mikethompson18:12:53

There is no ordering of effects

andre19:12:26

@mikethompson thank you for the re-frame, i'm really enjoing reading the docs, and working with re-frame

andre19:12:44

there are tons of useful links

andre19:12:05

and information

mikethompson19:12:26

np. I'm glad you like it. I'm working away on better docs in develop /docs/WIP

andre19:12:43

yes, i'm reading it too

mikethompson19:12:44

But the struggle is to explain things that happen over time

mikethompson19:12:00

And there's a bit of that with subscriptions etc

mikethompson19:12:37

Plus, the interceptor stuff, as your diagram shows

andre19:12:37

Yes, but result is very good, just need to carefully read. In the first time I read between the lines and paid for it, the second time when re-read carefully, wondering how everything is well documented

mikethompson19:12:21

I appreciate you saying that. There's blood sweat and tears in those docs. :-)

mikethompson19:12:33

Way, way more work than the code :-)

andre19:12:16

Yes, and it is felt, when reading those docs, thank you