Fork me on GitHub
#reagent
<
2017-10-30
>
cmal11:10:36

Hi! How can I add a parameter to the page function of (r/render [#'page] (.getElementById js/document "app"))?

cmal11:10:34

so [page app-state] is just a reagent component.

cmal11:10:07

I wonder why so many people use [#'page] instead of [page].

gadfly36111:10:40

I am not too familiar with that idiom, but I imagine it is when you want to make sure page doesn't get stale. My guess would be when it comes to routing and you are swapping in and out different pages under the same name. I do something like this: https://github.com/gadfly361/reagent-figwheel/blob/master/src/leiningen/new/reagent_figwheel/src/cljs/core_routes.cljs#L69-L71 instead

cmal11:10:16

Not quite understand but Thanks. @gadfly361

pesterhazy12:10:57

@cmal, #'page is a Clojure idiom that is now usable in ClojureScript as well

pesterhazy12:10:11

the idea I think is to achieve late binding, i.e. the function is only resolve when the component is rendered

cmal12:10:07

Oh. I will write that down.

pesterhazy12:10:33

compare how these two functions make-map and make-map2 compile down to js: http://app.klipse.tech/?cljs_in.gist=pesterhazy/3bfa08ac9ae8d62e325d2818443cb0e4

pesterhazy12:10:30

if I run make-map once and keep the result and then change the foo fn, the map will still refer to the old foo

pesterhazy12:10:54

make-map2 basically uses something like function(args){cljs.user.foo.apply(args)}

pesterhazy12:10:15

i.e. it resolves cljs.user.foo at call time, not definition time

pesterhazy12:10:35

n.b., vars referring to functions can be called as it they were those functions

pesterhazy12:10:05

so except for the effect I mentioned (foo 1) is equivalent to (#'foo 1)

pesterhazy12:10:15

@cmal, does that make sense?

cmal12:10:55

Thank you very much @pesterhazy. I think this is why they use #'page, just for figwheel to hot reload the page.

pesterhazy12:10:45

a similar trick is used for reloading for ring handlers in Clojure

pesterhazy12:10:00

there, too, late binding is desirable

cmal12:10:51

Thanks. 😄

eoliphant19:10:49

Hi, I have a quick question. I have a form-1 component, that I needed to give some local state. So I dutifully fn’ed the body, passing outer functions, args etc, but now I’m getting a React error: “Warning: Failed prop type: Invalid prop children supplied to t, expected a ReactNode.“

gadfly36119:10:06

@eoliphant It is hard to understand what you mean, perhaps provide a code sample? However, I am guessing you may be doing something like in foobar below ... try to do it like foobar2 instead.

(defn foobar [open?]
  (when open?
    [:h1 "I am open"]))

(defn foobar2 [open?]
  [:div
   (when open?
     [:h1 "I am open"])
   ])

eoliphant19:10:57

give me a sec will post it. The weird thing is that again, it works just fine as a form 1

gadfly36119:10:10

oh, i misunderstood, i thought you were using a form-1. i understand now you are converting a form-1 to a form-2 component

eoliphant19:10:43

ah yeah, moving it to form-2 is where it blows up

eoliphant19:10:37

ah crap lol snippets aren’t working

eoliphant19:10:54

ok so here’s the form-1

(defn field-wrapper
  "docstring"
  [field fieldfn]
  (let [mouse-over-up (r/atom false)]
    (fn [field fieldfn]
      ^{:key (:field/id field)}
      [sa/Segment {:id       (str (:field/id field) "-wrapper")
                   :on-click #(rf/dispatch [:field-selected-id (:field/id field)])
                   :color    (if (= @(rf/subscribe [:selected-field-id]) (:field/id field))
                               "blue"
                               "white")}
       [sa/Segment {:size      "mini"
                    :floated   "right"
                    :basic     true
                    :compact   true
                    :className "designer-field-menu"

                    ;:padded  false
                    }
        [:p (str "Status: " @mouse-over-up)]
        [sa/Icon {:name           "arrow up"
                  :circular       true
                  :link           true
                  :inverted       @mouse-over-up
                  :on-click       #(print "clicked")
                  :on-mouse-enter #(do
                                     (print "entering: " @mouse-over-up)
                                     (reset! mouse-over-up true))
                  :on-mouse-leave #(do
                                     (print "exiting: " @mouse-over-up)
                                     (reset! mouse-over-up false))

                  }]
        [sa/Icon {:name "arrow down" :circular true}]]
       fieldfn]))
  )

eoliphant19:10:08

wait sorry that’s the form 2 that doens’t work

eoliphant19:10:02

here’s the form-1 plus some context. THis works fine

(defmulti render-field :field/type)

(defn field-wrapper
  "docstring"
  [field fieldfn]
  (let [mouse-over-up (r/atom false)]
    ^{:key (:field/id field)}
    [sa/Segment {:id       (str (:field/id field) "-wrapper")
                 :on-click #(rf/dispatch [:field-selected-id (:field/id field)])
                 :color    (if (= @(rf/subscribe [:selected-field-id]) (:field/id field))
                             "blue"
                             "white")}
     [sa/Segment {:size      "mini"
                  :floated   "right"
                  :basic     true
                  :compact   true
                  :className "designer-field-menu"

                  ;:padded  false
                  }
      [:p (str "Status: " @mouse-over-up)]
      [sa/Icon {:name         "arrow up"
                :circular     true
                :link         true
                :inverted     @mouse-over-up
                :on-click     #(print "clicked")
                :on-mouse-enter #(do
                                   (print "entering: " @mouse-over-up)
                                   (reset! mouse-over-up true))
                :on-mouse-leave #(do
                                   (print "exiting: " @mouse-over-up)
                                   (reset! mouse-over-up false))

                }]
      [sa/Icon {:name "arrow down" :circular true}]]
     fieldfn])
  )
(defmethod render-field :input
  [field]
  (field-wrapper field [sa/FormInput {:id    (:field/id field)
                                      :label (:field/label field)}]))

gadfly36119:10:51

Can you try changing your defmethod to this?

(defmethod render-field :input
  [field]
  [field-wrapper field [sa/FormInput {:id    (:field/id field)
                                      :label (:field/label field)}]])

eoliphant19:10:24

ah yeah ok, let me try that

eoliphant19:10:27

that did it!

eoliphant19:10:36

there was an ‘interesting’ side effect though

eoliphant19:10:39

once I did that

eoliphant19:10:56

react started complaining about the :key being missing

eoliphant19:10:12

so I moved it into the render-field

eoliphant19:10:15

and it’s fine

gadfly36119:10:45

that sounds right

eoliphant19:10:05

I never paid much attention to that in particular just did it because the docs said so lol, but that’s a little confusing. It’s an issue with the ‘site’ of the key metadata in that case?

gadfly36119:10:32

@eoliphant Does looking at it like this help illustrate where the metadata needs to be?

;; Works
(for [x (range 10)]
  ^{:key x}
  [:div x])


;; Works
(defn render-x [x]
  [:div x])

(for [x (range 10)]
  ^{:key x}
  [render-x x])


;; Throws key warnings
(defn render-x2 [x]
  ^{:key x}
  [:div x])

(for [x (range 10)]
  [render-x2 x])

gadfly36119:10:25

and for completeness

;; Works
(defn render-x3 [x]
  ^{:key x}
  [:div x])

(for [x (range 10)]
 (render-x3 x))

gadfly36119:10:00

The difference between the one that fails and the ones that work is that you are rendering a function that eventually becomes a reagent component. If it was just a vector, like in my last example, then the metadata would work as you expect ... but i dont recomment using ( when using reagent, and instead just put the metadata outside of the function

eoliphant19:10:25

ah right right. the fact that I was using {} kind of hid the issue

eoliphant19:10:52

that’s what threw me

eoliphant19:10:56

thanks again

eoliphant19:10:32

because at first I was like “well, where’s my referential transparency??” lol