Fork me on GitHub
#reagent
<
2015-07-31
>
pupeno09:07:06

What do people think of re-frame?

caskolkm10:07:11

@pupeno: try the #C073DKH9P channel 😉

caskolkm10:07:44

but re-frame is pretty nice and simple simple_smile

pupeno11:07:25

caskolkm: nice, thanks.

gadfly36114:07:27

@caskolkm @pupeno it is more than fine to ask opinion of re-frame in this channel, since re-frame is a library for reagent and you may get more mixed opinions in this channel than you would in re-frame channel. That said, I love re-frame!

caskolkm15:07:41

@gadfly361: it was just a hint

ulsa16:07:32

having trouble getting a reaction to trigger inside a document.ready callback

(defn weights-page-did-mount []
  (.ready (js/$ js/document)
          (fn []
            ...
            ;; TODO this does not fire for some reason
            (reaction
              (let [validator (.data (js/$ "#form-search") "bootstrapValidator")]
                (print-state (str "revalidating due to changed " @max-total-weight))
                (.revalidateField validator "in-total-weight"))))))

curtosis16:07:05

I can't seemt to put my hands on an example of a select component (load from ajax, on-select swap a value into another component). Any pointers?

roberto16:07:44

are you using re-frame?

roberto16:07:35

seems like it would be non-trivial with re-frame if on-select you dispatch, and you also have a subscriber for changes on that select option.

curtosis16:07:40

not yet, anyway.

roberto16:07:56

i would highly recommend it

curtosis16:07:29

I'm looking into it, but I'm not ready to re-wire (ha!) everything just yet

roberto16:07:39

yeah, I know how that feels

roberto16:07:02

I started doing just reagent and when I started feeling some pain, I spent some time on re-frame

roberto16:07:16

but I was working on a side project that is disposable, so I could start from scratch

curtosis16:07:59

can I just do something like [:select {:onchange (fn [e] ...)} ...] ?

roberto16:07:09

even if you don’t use re-frame, the concept should help you organize the state in your vanilla reagent app

curtosis16:07:34

using select-options to build the options stuff inside, tied to a r/atom

roberto16:07:41

hmm, I don’t recall the event off the top of my head. Is it on-change or on-select?

curtosis16:07:25

should be onchange in js, which would be on-change in reagent, right?

curtosis16:07:10

on-select is for selection of text

roberto16:07:28

on-change #(my-fn (-> .-target .-value %))

curtosis16:07:45

in theory that should fire when the r/atom changes too, right?

roberto16:07:17

(defn my-fn [val] 
    (modify my atom with val)

roberto16:07:29

no, it won’t fire when the atom changes

roberto16:07:50

well, it depends on what you have the selected value set to

roberto16:07:13

but, I would think it only gets fired when a new option is selected.

curtosis16:07:51

:on-change #(reset! value (-> % .-target .-value)

roberto16:07:13

is value your atom?

curtosis16:07:39

or, in my case, :on-change #(swap! state assoc :selected (-> % .-target .-value))

curtosis16:07:08

stole the first one from the reagent todo example simple_smile

curtosis17:07:25

grrrrrrr.... that change was easy, but restarting figwheel broke on a class not found (from my server-side java code!)

ulsa18:07:24

anyone wants to have a look at a sample project that fails to trigger a reaction from a document.ready callback? https://github.com/ulsa/bvtest

ulsa21:07:08

Can't get it to work. Very frustrating. Doing exactly this in Hoplon using cell=.

roberto21:07:42

I’ve never used anything inside a document.ready

roberto22:07:49

btw, you shouldn’t need document.ready

roberto22:07:52

why are you using that?

ulsa22:07:29

the form element must exist, since I do js/$ on it to get the validator

ulsa22:07:42

in Hoplon, I got errors in the cell= if I tried it outside ready, so I placed it there and it worked nicely

ulsa22:07:22

but I've tried the reaction outside ready too, and it still doesn't trigger

ulsa22:07:57

is it enough to just reference a ratom in the reaction code?

roberto22:07:31

component-did-update does that for you

roberto22:07:46

it only gets executed when the component is rendered for the first time

ulsa22:07:52

I got the idea from recipes at reagent-cookbook

ulsa22:07:13

anyway, not sure ready is the problem, since it's not triggering outside either; am I missing something about reactions?

roberto22:07:14

that looks weird to me

roberto22:07:26

can you try it without the ready?

gadfly36122:07:52

@ulsa Are you using :component-did-mount? When creating your component?

ulsa22:07:10

no, see above

ulsa22:07:38

oh, sorry, yes I do

ulsa22:07:55

thought you meant did-update

roberto22:07:59

I’ve never had to use document.ready if I use react’s lifecycles

ulsa22:07:26

so just a fn plugged into that lifecycle keyword then?

gadfly36122:07:09

Yeah, react life cycles are preferred. I should check that recipe, waiting for document ready AND using component-did-mount might be unnecessary.

ulsa22:07:25

tried component-did-update, no compile; that's what you said @roberto right?

roberto22:07:09

yeah, did you push to github?

ulsa22:07:17

pushed now

ulsa22:07:51

changed back to component-did-mount, just a defn, it compiles, but no change from earlier

roberto22:07:23

ok, trying locally

ulsa22:07:21

I suppose component-did-mount is enough, since that point guarantees a dom representation of the component.

roberto22:07:02

what should be the correct behavior? I can load the page

ulsa22:07:49

tried to describe the steps in readme

ulsa22:07:08

3001 in total, 2000 in unloaded, next tab, change from A to B

ulsa22:07:30

first tab should be changed from invalid to valid, but that doesn't happen; works in hoplon

ulsa22:07:50

max total is 3000, but a reaction checks for B and then changes max to 4000

ulsa22:07:20

another reaction should look at max total and trigger revalidate, but I can't see that it does anything

ulsa22:07:22

manually going back to first tab revalidates due to onTabShow, so revalidate itself works

roberto22:07:08

this is a lot of code, a little hard for me to follow, but one of the first things that jumps to me is that your reaction is “outside”.

roberto22:07:34

so I would use form-2: and do the reactions inside a let, similar to how it is done in re-frame.

roberto22:07:19

(defn weights-page-component []
     (let [max-total-weight (reaction (if (= "B" (:eligibility @state)) 4000 3000))]
         (create-class {:component-did-mount weights-page-did-mount
                                        :render (fn [] (render-here)))

roberto22:07:35

the main difference with your one, is the let

ulsa22:07:51

OK, try to get state local to the component, if possible

roberto22:07:29

yeah, that way, max-total-weight is within the same scope as the function that renders

ulsa22:07:01

but what about the other reaction that needs to look at max-total-weight?

roberto22:07:06

this is from my own code:

roberto22:07:09

(defn main-panel
  []
  (let [store (subscribe [:new-shop])
        loc (subscribe [:new-shop/location])
        loading? (subscribe [:new-shop/loading?])]
    (create-class
     {:component-did-mount #(dom/register-mdl-components)
      :reagent-render 
      (fn []
        [:div
         [:section {:class "section--center mdl-grid mdl-grid--no-spacing mdl-shadow--2dp"}
          [title-view]]
         [:section {:class "section--center mdl-grid mdl-grid--no-spacing mdl-shadow--2dp"}
          (if @loading?
            [:div {:class "mdl-card mdl-cell mdl-cell--12-col-desktop mdl-cell--8-col-tablet mdl-cell--4-col-phone"}
             [:section {:class "mdl-card__supporting-text"}
              [:h5 "Acquiring location coordinates...."]]]
            [registered-form])]])})))



roberto23:07:01

the subscribes can be translated to something like loc (reaction (something something)

roberto23:07:58

and from re-frame’s docs:

(defn items-list         ;; Form-2 component - outer, setup function, called once
  []
  (let [items   (subscribe [:sorted-items])   ;; <--   subscribe called with name
        num     (reaction (count @items))     ;; Woh! a reaction based on the subscription
        top-20  (reaction (take 20 @items))]  ;; Another dependent reaction
     (fn []
       [:div
           (str "there's " @num " of these suckers. Here's top 20")     ;; rookie mistake to leave off the @
           (into [:div ] (map item-render @top-20))])))   ;; item-render is another component, not shown

ulsa23:07:52

I guess I can wrap render, did-mount and create-class in a closure that let's max-total-weight

ulsa23:07:30

but is that really different from having it in global scope?

roberto23:07:53

so, when it is inside the fun scope, it is saying:

roberto23:07:11

track this state, and re-render when any of these changes….

roberto23:07:16

when it is in global scope it is saying:

roberto23:07:21

render this view

roberto23:07:38

it is not informing the render function of any state it should be observing

roberto23:07:54

okay, i got to step away. I’ve been fighting with aws all day long and I’m frustrated.

ulsa23:07:13

thx a lot, I'll struggle on

roberto23:07:34

i’d suggest you read the re-frame readme

roberto23:07:52

even if you don’t use it, but the concepts will help you with what you are trying to do

ulsa23:07:20

Moved all state inside component, as suggested, which makes it better I guess, but still no trigger on the revalidate reaction. I'm probably missing something about how reaction works compared to Hoplon's cell=.

ulsa23:07:59

Even if the actual revalidation didn't cause a DOM update due to some React thing, I figure the print called from the reaction should be seen in the log, but I don't see it.

antishok23:07:59

@ulsa: reactions are tricky if they are not derefed inside a render function, as I've written here https://github.com/reagent-project/reagent/issues/116 using reagent.ratom/run! instead of reaction for your validation reaction should fix it