Fork me on GitHub
#re-frame
<
2016-05-25
>
nilrecurring09:05:47

@mvaline: the component is literally what I posted:

(defn exec-scripts [scripts]
  [:div
    (map (fn [s]
           [:script {:dangerouslySetInnerHTML {:__html s}}]) 
     scripts)])
and each script is something like function () { part that should execute... }();

nilrecurring09:05:36

@sbmitchell: thanks for the snippet example! 🙂 I'm not loading an external file though, just trying to execute some js on the spot

nilrecurring09:05:04

At this point I think it's wiser to rewrite all those little things in cljs...

pesterhazy13:05:08

@superstructor: don't tie yourself to core.async if you don't have to

pesterhazy13:05:54

my recommendation is to start with a simple base (perhaps cljs-ajax? it's nice and works great for us)

pesterhazy13:05:55

@nilrecurring: you can probably inject the script tag into the html head manually

nilrecurring13:05:03

@superstructor: I second the suggestion of pesterhazy on cljs-ajax, works great in all my projects 🙂

nilrecurring13:05:47

@pesterhazy: something like creating the new element with (js/document.createElement "script") and then (js/document.head.appendChild new-script)

nilrecurring13:05:58

I guess that would work

nilrecurring13:05:33

But already rewriting the things in cljs, I figured out that in js they would be unmantainable anyways 🙂

pesterhazy13:05:20

sure that sounds great too

pbaille14:05:05

hi! i’ve got a little re-com question is it the right place?

pbaille14:05:24

when I swap the model of a datepicker comp to another month, the ui stay on the same month

pbaille14:05:40

but the selected date is right

pbaille14:05:06

I have to manually go to the right month

sbmitchell16:05:09

Maybe youll get more hits #C0620C0C8 but I suppose most people here in re-frame are using reagent and possibly re-com 😛

sbmitchell16:05:59

Has anyone done anything with generative testing just using re-frame handlers to validate a workflow thru each step?

sbmitchell16:05:56

Ex. I have a login page with its own handlers for auth, logout, and form fields. It would be interesting to generate a test by setting up workflows as a tree data structure of handlers which you could like run a tree-seq on to evaulate all paths of a workflow

sbmitchell16:05:10

this is without interaction with the dom of course

fasiha16:05:18

I have a burning secret: I don't understand Reagent at all (and yet use re-frame a lot)… 😞

sbmitchell16:05:37

I think reagent is the easier wrapper of react to understand 😛 you just write functions

sbmitchell16:05:02

lifecycles are probably required for more interesting stuff but for the most part its just writing functions heh

sbmitchell16:05:49

and you dont need to understand virtual dom loveliness though that stuff is quite interesting to read about

shaun-mahood16:05:42

@fasiha: I'm kind of at the same place - Reagent is just too easy to use, but I end up having to go back and re-read the basics when I run into problems. Planning to do a toy re-implementation of re-frame in Rum at some point to force myself to get a better understanding of how things work without all the magic.

sbmitchell16:05:15

yea the reaction / ratom stuff is pretty magical

nilrecurring16:05:38

@fasiha: I used re-frame for 1y before actually having to understand all the components lifecycle thing

nilrecurring16:05:53

Everything is pretty magical and just works

fasiha16:05:05

In reagent, instead of subs/handlers, each "view" (react component) contains its own state and manually hands off pieces of it to children?

nilrecurring16:05:06

That is the essence of good abstractions

fasiha16:05:31

I still need to digest the react docs on lifecycles, I haven't run into a situation which drove me to read that section

shaun-mahood16:05:42

@nilrecurring: Totally. re-frame and reagent is one of the abstractions that just seems to work without having to think about it, pretty nice compared to a lot of other things.

fasiha16:05:49

I spent the last 3 months on a re-frame app and shipped it today for Real Work (first experience with cljs/react/etc.)

shaun-mahood16:05:13

@fasiha: Congratulations! Is it public facing?

fasiha16:05:14

and the amount of things I don't understand is terrifying me right now

shaun-mahood16:05:20

I've found re-frame to be relatively easy to refactor as bugs are found etc., so don't worry too much

nilrecurring16:05:48

@fasiha: congrats! I feel you, all my cljs stuff is not public facing as well 😞 I love how lifecycles are described in the re-frame wiki: " While you'll ignore Form-3 components most of the time, when you do need them, you need them bad."

sbmitchell17:05:23

I actually use form-3 components majority of the time now to be honest

sbmitchell17:05:43

especially for anything that needs to be composable and actionable from a parent. In the externally controlled component scenario you always need a state update from component-will-receive-props to update the internal state of the child component

mccraigmccraig18:05:02

@sbmitchell: i think i tend to use form-2 with a state r/atom updated in the inner render function for state updates... what's the advantage to form-3 there ?

sbmitchell18:05:57

you put state change calls inside the render fn? wouldnt you then need terminating conditions wrapping every state change

sbmitchell18:05:24

if Im using form-3 I find having the state external in a let binding is a lot more clear as far as what its closing over

sbmitchell18:05:32

I think a lot of it is just preference

sbmitchell18:05:52

there was something about the closures that @mikethompson had brought up in a previous discussion here

sbmitchell18:05:16

oh you are saying (let [state (r/atom val)] (fn [])

sbmitchell18:05:27

was confusing that with using with-meta

sbmitchell18:05:49

the only advantage of form-3 is that you can add lifecycles at that point

sbmitchell18:05:25

like I said...when you have a "toolkit" of components that may need to have internal state + have external control like for form components where you really want to be able to control state from the outside

sbmitchell18:05:32

you will need form-3 to handle the lifecycles better

mccraigmccraig18:05:04

yeah, that's true... toolkit components often seem to need lifecycles

sbmitchell18:05:12

yea thats kind of what I was referring too mostly

sbmitchell18:05:25

plus pretty much anything that is a container component will need them too...

sbmitchell18:05:33

so then I end up with 90% of components using form-3

sbmitchell18:05:59

I suppose there is an equivalent way to do with form-2 style

sbmitchell18:05:03

passing in the atom etc

sbmitchell18:05:35

but I prefer to only pass in simple data structures into components at all times..so always derefed or have it avail from within the closure

sbmitchell18:05:39

There is also the fact that to trigger fetches for re-frame I dispatch inside of component-did-mount to load a particular field of interest that the comp would subscribe too

mccraigmccraig18:05:56

hmm... i don't think i pass in atoms anywhere, though i do pass in an occasional function into some components... and i do have a pubsub thing for some bus-style comms

sbmitchell18:05:16

well there is no way around not passing fns around..I think some of the older reagent examples passed down atoms

sbmitchell18:05:20

that you would then reset inside of the child

sbmitchell18:05:26

but I prefer it have it go 1 way

sbmitchell18:05:32

like react wants it to be

mccraigmccraig18:05:56

if i'm doing a form-3 i'll use component-did-mount for fetches, but otherwise in a form-2 i'll just put the fetch before the inner render fn in the form-2 closure

sbmitchell18:05:09

yea but what if its not a 1 time fetch

sbmitchell18:05:16

then you may need to do it in component-did-update as well

sbmitchell18:05:20

not sure how form-2 works with that

sbmitchell18:05:26

does it re-init the component

mccraigmccraig18:05:40

yeah, that wouldn't work with form-2

sbmitchell18:05:36

you can probably get around component-did-update by starting a "subscription" (not re-frame sub) but an actual backend sub w/ websockets or something that would push data into the field you were initially intersted from the original fetch

sbmitchell18:05:30

then its a single call and reactions come from the generated subscription in the future

sbmitchell18:05:38

thats a pattern I was intersted in trying in my current app

sbmitchell18:05:54

that would require a full push model of course

mccraigmccraig18:05:46

i do have updates from the backend - i use a websocket with a go-block which dispatches to re-frame handlers and then that flows to reagent components via re-frame subs

sbmitchell18:05:14

so you basically have 2 event loops running the entire app?

sbmitchell18:05:19

one form re-frame to do event handlers

sbmitchell18:05:23

then one to dispatch to more handlers?

sbmitchell18:05:27

that you run

mccraigmccraig18:05:03

yes, you can look at it like that

sbmitchell18:05:12

how has that worked for scale

mccraigmccraig18:05:34

scale on the UI ?

mccraigmccraig18:05:42

or are you meaning elsewhere ?

sbmitchell18:05:47

as far as the events

sbmitchell18:05:15

Im trying to imagine how your own dispatcher knows what dispatch calls to make

sbmitchell18:05:30

do you wrap all fetch handlers to a registry

sbmitchell18:05:10

this is helping me btw thanks 😉 I need to implement something very similar in flow like now 😛

mccraigmccraig18:05:39

oh, it's pretty simple... there will be a registry when i get around to it - there's just a big core.match pattern-match atm

sbmitchell18:05:48

ahh core.match

sbmitchell18:05:13

seems like it would be pretty simple to just have a simple hash-map cache for the registry

sbmitchell18:05:01

subscription-topic -> vector of registry handlers perhaps

sbmitchell18:05:49

each fetch handler could have middleware to insert into the registry and start the sub or something

sbmitchell18:05:31

will ponder some more 🙂 thanks

mccraigmccraig18:05:34

yeah, i put [tag, val] records onto the websocket, and you can dispatch on the received tag easily with a map-registry

mccraigmccraig18:05:49

and then do whatever you like with the val

sbmitchell18:05:58

have you done any workflow testing that way using only the event handlers

sbmitchell18:05:59

so like given a tree structure of events -> do a depth first traversal to do handler mutations -> compare end db to expected

sbmitchell18:05:58

obviously one off handler tests are nice but I want to try some sort of generative pattern

sbmitchell18:05:07

so I can just define them as a data structure to run 😛

mccraigmccraig18:05:28

yeah, that would be nice

sbmitchell18:05:44

seems very possible as long as everything runs thru the centralized store

nilrecurring18:05:53

@mccraigmccraig @sbmitchell following your interesting discussion my mind went wondering: is there anything in cljs to do pubsub over websockets?

nilrecurring18:05:40

like: event with some key comes -> gets dispatched on a handler

mccraigmccraig18:05:21

@nilrecurring: are you thinking of a cljs client subscribing to a bunch of topics via a websocket ?

nilrecurring18:05:33

@mccraigmccraig: yep. It's fairly easy to roll your own, since it's just agreeing on a protocol with the server and then keeping a hashmap with the handlers mapped, and having a dispatch function

sbmitchell18:05:52

yea my company rolled their own

sbmitchell18:05:16

I did not write that particular section of the code but basiaclly it follows how MDN describes how to interface into websockets

sbmitchell18:05:20

using pings etc to keep it alive

mccraigmccraig18:05:24

i do it with gnatsd on the backend

sbmitchell18:05:26

and then there is transit

sbmitchell18:05:57

then we have compojure routes that are just on /ws and the cmd are dispatched to our api fns

nilrecurring18:05:46

yea, I usually roll my own too

nilrecurring18:05:42

But it would be nice to have everything already implemented. I didn't actually used sente, but it seems that it doesn't have a pubsub

sbmitchell18:05:17

I have not personally used it so I cant comment

sbmitchell18:05:22

there was a cool video where the author made a multi-user snake game though

mccraigmccraig19:05:19

@nilrecurring: gnatsd and my very own https://github.com/employeerepublic/clj-nats-async do very nicely for pubsub on the backend... then it's trivial to wire up to your client via a websocket with aleph and manifold

superstructor20:05:39

thanks for all the advice re http lib, I’ll give cljs-ajax a try @pesterhazy @nilrecurring @mikethompson @sbmitchell