Fork me on GitHub
#re-frame
<
2016-12-06
>
cmal01:12:06

@sandbags: what about adding a flag to db, when view changed, set the flag to another value, and when dealing with the 'later' event, check the value of the flag?

mikethompson01:12:41

Re-frame is about to get a completely new README It is in the develop branch If anyone has time, can they proof read it please, give me a PR of any typo fixes. https://github.com/Day8/re-frame/blob/develop/README.md If you have even more time there's also: https://github.com/Day8/re-frame/blob/develop/docs/CodeWalkthrough.md These docs changes will be announced as part of the 0.9 release (currently in alpha)

cmal05:12:04

'3. An Interceptor Chain is executed in two stages. First a forwards sweep in which all :before functions are called, and then second, a backwards sweep in which the :after functions are called. A context will be threaded through all these calls.' Does this 'backward sweep' mean that all :afters are executed in the reverse order as of the order how all :befores are executed?

ricardo07:12:51

@mikethompson Reading. I see you removed the conveyor belt graph. For what it’s worth, I think that was very illustrative.

mikethompson07:12:15

Do you means this

app-db  -->  components  -->  Hiccup  -->  Reagent  -->  VDOM  -->  React  -->  DOM
 ^                                                                              |
 |                                                                              v
 handlers <-------------------  events  -----------------------------------------
                          a "conveyor belt" takes events
                          from the DOM to the handlers

mikethompson07:12:38

Hmm. Wondering how to weave that in.

ricardo07:12:37

You could re-do it in terms of the six dominoes, since in the end the DOM is used for the user to trigger events again.

ricardo07:12:29

Held a Clojure workshop on Saturday. Explaining re-frame quickly people were mostly nodding along, in that “yes, yes, understanding but not yet seeing it” sort of way.

ricardo07:12:39

At least most of them.

ricardo07:12:43

When they saw the conveyor belt graph, it clicked.

mikethompson07:12:27

I think I'll need a diagram which better matches the new dominoes narrative

mikethompson07:12:39

Are you sure the water cycle doesn't do it :-)

ricardo08:12:19

As an analogy? Yeah. If someone’s reading the whole thing. But you have to assume that the first encounter of anyone with re-frame will be by quickly scanning through it.

ricardo08:12:44

The brain will likely discard the image as local color. The equivalent of an xkcd reference.

ricardo08:12:21

I’m curious… why have the basic example with reg-event-fx?

andre08:12:51

i think because reg-event-fx is the basic function

andre08:12:55

reg-event-db is modifed reg-event-fx for special cases

andre08:12:43

when you want to change only db and you don't have coeffects

ricardo08:12:16

Hmm. Maybe. But I think most beginners will only care about returnning the new database, not coeffects, and reg-event-db scans much cleaner.

andre08:12:57

yes , but in future it can be confusing

ricardo08:12:58

My take on it would be that anyone who wants to dig into it, can, but that the README should take the most basic approach. Make things as basic as possible for newcomers to the library and approach. Maybe mention the other two reg-event-* and link to them, but not necessarily start there.

ricardo08:12:57

Without knowing that reg-event-fx handlers can return and receive something else than just the database, getting and returning a hashmap just reads like noise.

ricardo08:12:48

Particularly since the query acts directly on the database.

ricardo08:12:08

Just trying to think like a complete newcomer here. Having a reg-event-db handler on dominoes 2/3 would scan cleaner and more cohesive with #4 for a newcomer.

andre08:12:06

i think in reg-event-fx you should clear understand that you return instructions via data, and this is the key idea, and you should undertand this from the beggining, reg-event-db hides this idea, and this is not good

ricardo08:12:33

We have a difference of opinion there. I think presenting less noisy versions to newcomers is good. It makes it easier to get started. When they reach the limitations of the basic wrapper, then they can ask “hey, and how would I do X?” You’re not hiding knowledge, or asking them to treat something as an incantation. You’re just showing them first the option that they’re most likely to use.

curlyfry09:12:35

@mikethompson Awesome! I'll check them out later today (Swedish time)

mikethompson10:12:50

@ricardo the explanation to that point talks about how event handlers return a description of effects. That's an important concept if someone is going to get an initial feel for re-frame - I don't want to hide it. I felt the example had to reflect that concept OR I was going to have to unexplain that part. So, while reg-ervent-db is simpler it actually makes the explanation harder. I do understand what you are saying, but I'm comfortable with the decision to show reg-event-fx.

mikethompson10:12:27

To put that another way: using the more sophisticated reg-event-fx actually makes the code more consistent with the explained concepts.

ricardo11:12:01

@mikethompson In that case, I’d add a note on Domino 2 to indicate ”besides the database, the parameter contains [fill in the blanks], which we won’t talk about now but you can read about [on this page here]”.

ricardo11:12:33

That way it’s clear why that first parameter is a map instead of just the database.

mf12:12:22

Hi, hoping someone can let me know if it would be considered bad practice to have a general purpose db subscription handler in the form:

(register-sub
 :db
 (fn [db [_ path]]
   (reaction (get-in @db path))))
This would be used from a component like so:
(defn my-component []
  (let [bar (subscribe [:db [:foo :bar]])]
    (fn []
      [:p @bar])))
My initial thought was that this would be inefficient from a React point of view. Thinking that the component would re-render whenever ANY nested db value changed (not just when the bar value changed). It appears that the reaction does re-run whenever any value in db changes, however the component will only re-render if it's specific input signals change (i.e if bar changes). So my initial concerns about performance seem somewhat unfounded, however the solution still feels wrong to me. Interested if anyone can let me know if this is bad-practice and why. Thanks

andre13:12:16

db in sub is not an atom, so you don't need deref

andre13:12:15

you don't need reaction inside subscription

andre13:12:49

(defn my-component []
  (let [bar (subscribe [:foo/bar]])]
    (fn []
      [:p @bar])))

andre13:12:19

(register-sub
:foo/bar
 (fn [db_]
   (get-in db :foo :bar))))

andre13:12:58

path is not a good idea i think

mf13:12:57

@andre I was under the impression that the db argument implicitly passed to subscription handlers was a ratom

mf13:12:42

Also I thought the rule was to "always" return a reaction from subscription handlers, as their job is to return a value that changes over time.

andre13:12:40

subscrube making reaction around you sub

andre13:12:35

i didn't know about dynamic subscriptions, so i can't say now about their performance but from code view, it's easier to see all queries in one place, but maybe it depends on specific situation

mf14:12:46

@andre My understanding was that using Reagent 0.5.1 and Re-frame 0.6.0 the following was true: 1. The db argument implicitly passed to subscription handlers is a ratom 2. Subscription handlers, must return a "stream" of values that change over time (reaction). Your examples seem to suggest that this is not the case.

andre14:12:01

yes because we have now reagent 0.6.0 and re-frame 0.9.0 (alpha)

mf14:12:17

Yeah I'm not using those

andre14:12:21

i came in this beautiful world from re-frame 0.8.0

mf14:12:39

Yes my version is abit old

mf14:12:59

So the advice you are giving is relevant to the latest version only?

andre14:12:00

sorry i don't know anything about older versions

mf14:12:09

@andre no problem

mf14:12:17

thanks anyway

mf14:12:23

@andre It looks like Re-frame 0.8.0 added following change: "With reg-sub, you no longer need to use reaction explicitly". https://github.com/Day8/re-frame/blob/master/CHANGES.md#080--20160819

cmal14:12:16

Oh, thanks for mention that.

cmal14:12:40

I'm just confusing about this.

mf14:12:25

@cmal I'm just coming to accept that an upgrade to Re-frame 0.8.0 is overdue

mf14:12:54

although seems that there were quite a lot of breaking changes

mf14:12:50

I'm reading the updated README by @mikethompson which helps alot: https://github.com/Day8/re-frame/blob/develop/README.md

cmal14:12:58

Yeah, the docs are amazing! Clearly described. I learned a lot about the design patterns.

mf14:12:20

IMO the best README out there. Love it

mf14:12:42

and yes learned an absolute load from it

cmal15:12:16

And people here are kind and knowledgeable. I am new here and loves that.

mf15:12:33

that helps

danielgrosse15:12:34

Just have a component which should trigger the fullscreen on click. I dispatch a :toggleFullscreen handler, and in it, I call the requestFullscreen function of the goog.dom library. But Chrome gives me a warning, that Fullscreen depends on a user gesture. Is their a way to get it done with that way? I thought the user gesture depends on the time from click to the requestfullscreen call.

curlyfry16:12:43

@mikethompson With subscribe being ok in form-1 components, is the only need for form-2 components when you want to use a local reagent ratom?

curlyfry16:12:39

(Meaning not that often)

mikethompson19:12:35

@mf upgrading to 0.8 is fairly painless. Many code bases will handle the upgrade with zero changes (but you might get some deprecation warnings). There are some global renames to do (to avoid deprecation warnings). You really only have work to do if you wrote your own middleware.

eoliphant19:12:05

Hi, I’m new to re-frame, and I’ve been trying to find an example of the best way to handle form management/submission. I saw something about having forms do reagent stuff ‘privately’ then dispatch an event out. So, in say an :on-click, I should first do local validation, then fire off my event??

(defn test-form
  []
  (let [fields (r/atom {})
        error (r/atom nil)]
    ;(print "entering form")
    (fn []
      [:form.ui.form
       (text-input "First Name" :firstname "First Name" fields false)
       (text-input "Surname" :surname "Enter surname" fields true)

       [:div.field
        [:label "TextA"]
        [:textarea]]
       [:button.ui.button
        {:type     :button
         :on-click #(submit-monitoring-form! fields error)}
        "Submit"]])))
my
submit-monitoring-form
is currently just shooting off an AJAX request. So I’d replace/enhance that with my validation-then-dispatch?

mikethompson19:12:00

1. The text fields should have on-change which dispatch the newly entered value (which then gets stored in app-db) 2. The "Submit" button's :on-click should also be a dispatch which is handled by making the necessary HTTP request

mikethompson19:12:04

So view fucntions are as dumb as possible. They just dispatch. All the work is done in the event handlers

eoliphant19:12:16

ok, i’m still wrapping my brain around everything is part of the app state lol

eoliphant19:12:53

thanks will do a bit of refactoring

eoliphant20:12:26

that raises a style/convention question i guess. So would you conceivably have an event for every field in your app? Presumably namespaced to forms. Or would there be maybe one per form, that’s say takes field/value pairs as data?

mikethompson20:12:30

I can imagine either way working. I don't write many forms so I don't have first hand knowledge. I might leave it for others to jump in

eoliphant20:12:23

ok thanks 😉 will play around with it. I’ve the opposite problem, what i’m looking to do is very form ‘heavy'

mikethompson20:12:05

I can imagine (dispatch [:field-change :first-name "Barry"]) being effective

mikethompson20:12:02

(def-event-db 
   :field-change 
   (fn [db [_ k v]] 
      (assoc-in db [:fields k] v)))

eoliphant20:12:09

yeah that looks good, thanks. will just need to see how it ‘scales’ in terms of more forms etc. But gonna start with that 😉 thanks again 🙂

mac23:12:35

I am trying to move to re-frame-http-fx but I am having trouble with the cljs-ajax part. I have an api call that works with js/fetch and the request string produced by http-xhrio works when pasted into a browser, but still the request fails with a useless error from the server (which I don't control). Any ideas?

shaun-mahood23:12:13

@mac: Can you post some sample code?

shaun-mahood23:12:59

Also, make sure you are including cljs.ajax in your file or it won’t work.

mac23:12:46

cljs.ajax included 🙂

mac23:12:14

(defn ajax-get-meetups []
  (ajax/GET ""
             {:params  {:member_id member-id
                        :key api-key
                        :fields "self"
                        :only "id,name,status,venue.name,self.rsvp.response"}
              :response-format (ajax/json-response-format {:keywords? true})}))

mac23:12:01

@shaun-mahood Currently using a straight cljs-ajax function for debugging.

shaun-mahood23:12:49

@mac: Ok, what have you got for the http-fx translation of that?

shaun-mahood23:12:43

Ok, give me a second - I’ll give you a translation that should work to a reg-event-fx

mac23:12:47

@shaun-mahood The thing is the http string works in the browser, but both the ajax/GET reqyúest and the reg-event-fx equiv fails.

mac23:12:08

@shaun-mahood Which makes me think it is a header issue or something.

denisj23:12:33

@danielgrosse I suspect its not about the amount of time, but that the call stack can be traced back to a user initiated event, like a button click. Since re-frame processes your dispatched event on nextTick then this boundary is likely causing your warning

shaun-mahood23:12:45

@mac: That’s annoying - maybe try changing from the ajax/GET command to ajax-request - I thought it was working with cljs-ajax and just not with re-frame-http-fx, so I ay not be able to help much.

mac23:12:32

@shaun-mahood Tried that already 😞

mac23:12:44

@shaun-mahood Great conj talk btw.

shaun-mahood23:12:16

@mac: Maybe check in #clojurescript? Can you see any difference in the headers between working/not working in devtools?

shaun-mahood23:12:49

@mac: Oh, I just looked there - the other option could be to get it working with the google Closure version, then make your own fx handler (which shouldn’t be too hard)

mac23:12:46

@shaun-mahood The js/fetch version works no problem. Is there some guidance on how to do a custom fx handler?

shaun-mahood23:12:35

@mac: Yeah, it’s actually pretty easy (once you’ve figured it out, at least 🙂 ) - docs are the best place to start https://github.com/Day8/re-frame/blob/master/docs/Effects.md - and I’ve got a pretty simple one at https://github.com/smahood/whats-up-doc/blob/master/src/whats_up_doc/github_fx.cljs#L348 if you want to see how it works, it is using :http-xhrio but it might give you an idea of how one could work on top of what the docs have/

shaun-mahood23:12:36

@mac: Read the one you linked and the one I linked and you should be good 🙂

mac23:12:35

@shaun-mahood If the ajax call only fetches data is coeffects then the way to go?

shaun-mahood23:12:45

@mac: I'm not sure, I've thought of the ajax fetch as an effect and the return as another effect, but it would be easy enough to get it working as an effect and then move it to a coeffect and see what happens - it's something I've been thinking about the past few days but I haven't had a chance to test it.