Fork me on GitHub
#reagent
<
2017-04-09
>
urbank08:04:10

Is this statement true: if a reagent component takes a callback as an argument, it will always rerender if that callback is an anonymous function?

pesterhazy08:04:09

(def myfn (fn [] (println "boom")) (defn c1 [] [c2 myfn]))

pesterhazy08:04:25

Technically myfn is an anonymous fn 🙂

pesterhazy08:04:12

I'm kidding of course, but what about the interesting case? Let's check

pesterhazy08:04:45

(defn foo [] (let [f (fn [] (println "foo"))] (prn @x f (= @x f)) (reset! x f) nil))

pesterhazy09:04:43

If you call foo twice, it will still return false. So every time you create an anonymous fn, you get a new object that is not equal to the ones before

pesterhazy09:04:27

So I think that means that the statement is true, because props will always be different.

urbank09:04:10

I see. Thanks for the answer! I suppose a form 2 component could be used to get around that.

pesterhazy09:04:38

This shows that your suspicion is correct

pesterhazy09:04:34

Using Form-2 is an interesting workaround.

pesterhazy09:04:28

Although all of this only applies if you're not capturing any variables in the closure, in which case the inner component needs to be updated anyways

urbank09:04:38

Hm, perhaps an option would be to ignore functions when determining whether or not to update? This does imply that the callback function will never change on the fly (at least if all other arguments remain the same)

pesterhazy09:04:51

that's not a warranted assumption though

pesterhazy09:04:08

because if you use any vars in the fn, it will change

urbank09:04:49

True... another option would be to describe anonymous functions with a vector of a named function and the arguments that get passed into it.

urbank09:04:53

and in component (apply fn (concat args [...])) (or somthing.)

pesterhazy09:04:43

I think at this point it would be useful to look at your actual problem

pesterhazy09:04:08

because avoiding re-running component's render-fn is not a goal in itself

pesterhazy09:04:02

really the js/cljs part of react is fast, what you want to avoid is actual DOM manipulations, which don't occur in either outer1, outer2 or outer3 in my Klipse

urbank09:04:03

Yes, you're right of course. Not very common for this to be a problem I suppose 🙂 It's more of a potential problem I saw, since making an interactive component generic (which pretty much demands callbacks) seems to mean opting out of utilizing ShouldComponentUpdate

pesterhazy09:04:53

it's great that you pointed out the issue, I wasn't aware of it actually

pesterhazy09:04:18

or maybe in the back of my mind but not clearly

pesterhazy09:04:47

can you explain what you mean by opting out of utilizing ShouldComponentUpdate?

urbank09:04:23

I just meant that reagent uses identical? to decide on a rerender inside the React method ShouldComponentUpdate (at least that's what I assume, should probably read the source), so if identical? always returns false, you're not really using ShouldComponentUpdate

pesterhazy10:04:07

ah so what you're saying is that one option would be to override should-component-update?

pesterhazy10:04:27

basically to only consider a subset of the props

urbank10:04:25

Yes, but as you've said, assuming anonymous functions are always the same isn't quite valid

kokos11:04:27

(defn renderer 
  []
  [:div 
[:form {:method "post"
          :enctype "multipart/form-data"
          :name "uploadform"
          :style {:font-size "18px"}
          :action "/upload/afile"
          }
   [:input {:type "text"
            :name "filename"}]
   [:input {:type "file"
            :name "filefield"}]
   [:input {:type "submit"
            :value "Upload"}]]])




(defn component 
  []
  (r/create-class {:reagent-render renderer}))
everything renders but the :enctype "multipart/form-data" attribute, how would one push :enctype attribute into the displayed form tag ?

kokos12:04:36

correct attribute name should be :enc-type or "encType"

benbot13:04:27

Can someone give me a bit more detail on the :on-change line here

(defn input []
  [:input {:type "text"
           :value @state
           :on-change #(reset! state (-> % .-target .-value))}])

benbot13:04:43

I'm not sure what .-target is doing, or why you need the arrow syntax at all

pesterhazy13:04:57

on-change is a browser attribute set to a callback. The callback receives as its argument an event

pesterhazy13:04:31

The code sets state to (in JS) e.target.value

pesterhazy13:04:51

target referring to the input box, .value its contents

benbot13:04:09

oh right the .<whatever> is calling js

benbot13:04:19

makes sense -_-

pesterhazy13:04:21

.- is js interop syntax for accessing properties

pesterhazy13:04:49

(-> % .-foo .-bar) is equivalent to (.-bar (.-foo %))