Fork me on GitHub
#reagent
<
2017-03-02
>
minikomi04:03:53

I have a background image element which is not required on mobile. It is quite heavy and does some image preloading when it mounts using images with :on-load functions. I was surprised to find that (when (not @mobile) [bg-element @images]) actually was triggering the preloading events, even when @mobile is false

minikomi04:03:33

Is there a way to make the sub-component render only when @mobile is true?

minikomi04:03:23

oh wow.. I must be doing something wrong http://escherize.com/cljsfiddle/#gist=7a8425865976bed91bf94b7e1b11ce34 this only logs component1 as I'd expect..

minikomi04:03:53

I wasn't initializing the @mobile atom at the right time so it was defaulting to false 🤕

alanspringfield08:03:24

@pishty if you look at the Installation section of cljs-react-material-ui: https://github.com/madvas/cljs-react-material-ui/blob/master/README.md#installation, they mention that you need to exclude some packages to get onTouchTap event working

borkdude09:03:35

I recently heard here that Reagent doesn’t do well with multimethods. What is the reasoning behind this?

pesterhazy09:03:51

that's it. I haven't seen a bug report for this, but multiple reports of components failing to update because they're implemented as multimethods

tomaas10:03:39

hi, I get this error while trying to build with lein do clean, uberjar : java.io.FileNotFoundException: Could not locate prone/middleware__init.class or prone/middleware.clj on classpath., compiling:(middleware.clj:1:1)

tomaas10:03:55

I have some middleware functions I use in /env/prod/clj/middleware.clj as well as /env/dev/clj/middleware.clj

alanspringfield11:03:14

@tomaas could you post some source code related to the namespace prone.middleware or the relevant contents of /env/prod/clj/middleware.clj?

joshkh12:03:52

@pesterhazy a few days ago you linked me to your blog post about the :ref property. i just noticed an odd behaviour... maybe you know what's going on? in this example the function value of the :ref key on the [:input] element never gets called. (i added a :ref key to the outer div just to make sure that works, and i do get ref1 in the console, but not ref2):

(defn constraint-text-input []
  (let [component (reagent/atom nil)]
    (fn [& {:keys [value on-change on-blur allow-possible-values possible-values]}]
      [:div
       {:ref (fn [el] (println "ref1" el))}
       [:input.form-control.dropdown
        {:data-toggle "dropdown"
         :ref         (fn [el] (println "ref2" el))
         :type        "text"
         :on-change   (fn [e] (on-change (oget e :target :value)))
         :on-blur     (fn [x] (on-blur))
         :value       value}]])))

pesterhazy12:03:00

@joshk, I have a suspicion

pesterhazy12:03:39

first of all usually refs to inputs should work

pesterhazy12:03:58

reagent does some special handling for input elements, however

pesterhazy12:03:18

are you on reagent 0.6.0? there may be a recently fixed bug in earlier versions

joshkh12:03:30

looks like i am, yeah

joshkh12:03:01

it's not a show stopper and i can work around it. i'm just curious.

pesterhazy12:03:29

if you put your (minimized) example on klipse, I can have a look

pesterhazy12:03:53

btw what is data-toggle?

joshkh12:03:04

it might be that i'm excluding cljsjs/react and including react-with-addons

pesterhazy12:03:25

are you using some sort of bootstrap jquery plugin? that would explain why it doesn't work

joshkh12:03:47

ah yes, the full component is a bootstrap dropdown

pesterhazy12:03:56

then that's the problem

joshkh12:03:23

bootstrap strikes again..

pesterhazy12:03:29

it's always tricky to mix jquery (and other direct dom manipulation libs) and react

pesterhazy12:03:43

bootstrap is fine, as long as you keep the javascript addons out of it

joshkh12:03:22

that makes sense. okay thanks for the help! i'll try to avoid the js side of bootstrap as much as i can.

hlolli13:03:51

I have two components A->B, I update the local state of A, and the :component-did-mount of B, that btw is not being mutated at all, is being called for every local state change of A. Is there any way around is, maybe there's a parallel function in reagent to om's om/factory?

pesterhazy13:03:57

can you share the code?

pesterhazy13:03:15

otherwise it's hard to guess where the error may be

hlolli13:03:31

I cant make a minimal example, but I can try In component A I have resizeable table that I define here

:component-did-mount (fn [this]
                           (r/set-state this  {:column-border-1 142
                                               :column-border-2 172
                                               :column-border-3 175
                                               :column-border-4 172
                                               :column-border-5 162
                                               :column-border-6 162
                                               :column-border-7 182
                                               :column-border-8 190}))
I resize them in component A with swap! this is the beginning of component B and in read-from-uri is a re-frame reaction that fetched data, but in general, I think :component-did-mound shouldn't be called more than once.
(defn search-query-component []
  (r/create-class
   {:display-name "search-query-component"
    :component-did-mount (fn [this]
                           (let [search-query-local-state-atom (r/state-atom this)]
                             (read-from-uri search-query-local-state-atom)
                             (events/listen
                              js/document
                              EventType/KEYDOWN #(cond
                                                   (= 32 (.-keyCode %)) (.preventDefault %)
                                                   (= 27 (.-keyCode %)) (close-all-shelves search-query-local-state-atom)
                                                   (= 13 (.-keyCode %)) (search-with-enter-key search-query-local-state-atom @(rf/subscribe [:search/queries]))
                                                   (= 8 (.-keyCode %)) (swap! search-query-local-state-atom assoc :backspace? true)
                                                   (= 46 (.-keyCode %)) ;;DELETE KEY
                                                   (swap! search-query-local-state-atom assoc :delete? true)
                                                   :else (when (or (:backspace? @search-query-local-state-atom)
                                                                   (:delete? @search-query-local-state-atom))
                                                           (swap! search-query-local-state-atom assoc
                                                                  :backspace? false
                                                                  :delete? false))))
                             (events/listen
                              js/document
                              EventType/CLICK (fn [ev] (if-not
                                                           (or (.-defaultPrevented ev)
                                                               (:datepicker-default-prevent @search-query-local-state-atom))
                                                         (close-all-shelves search-query-local-state-atom))))))

hlolli13:03:24

well, most of this code is not related. But as I mutate these :column-border-x vals, nothing is suspicius from the same(this) component, only in the components that the component is rendering

hlolli14:03:56

Ok a more basic question, I define a react-component with defn B... and I want to render within a component, so I call it from A via :render (fn[] (B)). But wouldn't it make more sense, to "manufacture" the component first, like (def b (B)) and render it then, so that rerender won't have any effect on nested components?

hlolli14:03:46

that solved it. Did this

(def manufactured-search-query-component
  (search-query-component))
from its parent
[manufactured-search-query-component]

pesterhazy14:03:54

hm that doesn't make a whole lot of sense to me but glad it works for zou

hlolli14:03:11

it makes perfect sense to me, because if you make a function call in render, it's going to get re-called on re-render. But if you call the function once in a def, then rerender won't recall that function.

pesterhazy14:03:07

that's not how reagent works, but glad you got it working that way

hlolli14:03:19

lol ok, my only alternative theory would be that Im forgetting to give r/create-class a react-key, therefore react doesn't know if it needs to rerender.

pesterhazy14:03:59

no if the child key is missing, it should still work but issue a warning

pesterhazy14:03:13

a couple of things about your code

pesterhazy14:03:57

i wouldn't use r/state-atom etc but just use a ratom bound in a closure instead

pesterhazy14:03:26

search-query-local-state-atom should be defined outside create-class, otherwise it won't rerender correctly

pesterhazy14:03:43

plus you're passing around the state atom, which makes things complicated

hlolli14:03:51

ahhh ok, I think I understand you. Don't know why this is needed but I've seen it in reagent before so I'll do that.

pesterhazy14:03:16

better to pass callbacks fns to the child components

hlolli14:03:50

reagent seems to give a local-state atom for free, wanted or unwanted. I notice that reagent users love global states for even the most trivial transient states, of course differs. Maybe swapping the local-state-atom is a bad idea all togeather?

pesterhazy14:03:29

in general, I strongly prefer a single global state atom whereever possible

pesterhazy14:03:56

for ephemeral state, however, a local atom bound in a closure is also a good option

hlolli14:03:56

I see it that a component should be reuseable dataprocessing engine, it takes data and renders some data. If a text fields needs to transact to global atom that the user pressed the delete key or the mouse is hovering a div, is adding complexity in my opinion. What should flow trough the components should be remote-data, processed remote data, user inputs etc. Of course this talk is more of a talk that's usually not connected to the reality of front-end development.

pesterhazy14:03:18

you can pass around cursors

pesterhazy14:03:24

that usually does the job for me

pesterhazy14:03:05

but yeah, everyone needs to find their own way of using React; reagent is pretty unopinionated by itself

pesterhazy14:03:10

don't forget there are huge advantages to having all (non-ephemeral) state in a single atom: you can introspect the state (e.g. with data-frisk), you can serialize it and send to the server if a bug occurs, you can spec it etc.

hlolli14:03:27

yes, I know the benefits of it but don't do it as much as I should. I can blame a bit om for making mutations a bit painful to add and me wanting fast feedback. But yes, I'll have to try the re-frisk, which I haven't done yet.